# Largest row-wise and column-wise sorted sub-matrix

Last Updated : 30 May, 2022

Given an N * M matrix mat[][], the task is to find the area-wise largest rectangular sub-matrix such that each column and each row of the sub-matrix is strictly increasing.

Examples:

Input: mat[][] =
{{1, 2, 3},
{4, 5, 6},
{1, 2, 3}}
Output:
Largest sub-matrix will be {{1, 2, 3}, {4, 5, 6}}.
Number of elements in this sub-matrix = 6.

Input: mat[][] =
{{1, 2, 3},
{4, 5, 3},
{1, 2, 3}}
Output:
The largest sub-matrix will be
{{1, 2}, {4, 5}}

Approach: There are many approaches to solve this problem varying from O(N3 * M3) to O(N * M). In this article, an approach with O(N * M) time complexity using a stack will be discussed.
Before proceeding further, its recommended to solve this. problem.

Let’s try to understand the approach broadly, then the algorithm will be discussed. For every column of the matrix, try to find the largest row-wise and column-wise sorted sub-matrix having the left edge at this column. To perform the same, create a matrix pre[][] where pre[i][j] will store the length of the longest increasing sub-array starting from the index j of the array arr[i].
Now using this matrix, for each column j, find the length of the longest row-wise and column-wise sorted array. To process a column, all the increasing sub-segments of the array pre[][j] will be required. The same can be found using the two-pointer technique. In each of these sub-segments, simply find the largest area under the histogram considering the row-wise increasing sub-segments as bars.

• Create a prefix-sum array for each row ‘i’, which stores length of the largest increasing sub-array ending at each column ‘j’ of that row.
• Once we have this array, for each column ‘j’.
• Initialize ‘i’ equals 0.
• Run a loop on ‘i’ while ‘i’ is less than ‘N’
• Initialize ‘k’ equals i+1.
• while k less than N and arr[k][j] greater than arr[k-1][j], increment k.
• Apply histogram problem on the sub-array pre[i][j] to pre[k-1][j], to find the largest area under it. Let us call this value ‘V’. Update final answer as ans = max(ans, val).
• Update ‘i’ equals k-1.

Below is the implementation of the above approach:

## C++

 `// C++ implementation of the approach` `#include ` `using` `namespace` `std;`   `// Function to return the largest` `// area under a histogram` `int` `histo(vector<``int``> q)` `{`   `    ``// Stack` `    ``stack<``int``> q1;`   `    ``// Length of the vector` `    ``int` `n = q.size();`   `    ``// Function to store the next smaller` `    ``// and previous smaller index` `    ``int` `pre_smaller[q.size()];` `    ``int` `next_smaller[q.size()];`   `    ``// Finding the next smaller` `    ``for` `(``int` `i = 0; i < n; i++)` `        ``pre_smaller[i] = -1, next_smaller[i] = n;` `    ``for` `(``int` `i = 0; i < n; i++) {` `        ``while` `(q1.size() and q[q1.top()] > q[i]) {` `            ``next_smaller[q1.top()] = i;` `            ``q1.pop();` `        ``}` `        ``q1.push(i);` `    ``}`   `    ``// Finding the previous smaller element` `    ``while` `(q1.size())` `        ``q1.pop();` `    ``for` `(``int` `i = n - 1; i >= 0; i--) {` `        ``while` `(q1.size() and q[q1.top()] > q[i]) {` `            ``pre_smaller[q1.top()] = i;` `            ``q1.pop();` `        ``}` `        ``q1.push(i);` `    ``}`   `    ``// To store the final answer` `    ``int` `ans = 0;`   `    ``// Finding the final answer` `    ``for` `(``int` `i = 0; i < n; i++)` `        ``ans = max(ans, (next_smaller[i]` `                        ``- pre_smaller[i] - 1)` `                           ``* q[i]);`   `    ``// Returning the final answer` `    ``return` `ans;` `}`   `// Function to return the largest area` `// for the required submatrix` `int` `findLargest(vector > arr)` `{` `    ``// n and m store the number of` `    ``// rows and columns respectively` `    ``int` `n = arr.size();` `    ``int` `m = arr[0].size();`   `    ``// To store the prefix_sum` `    ``int` `pre[n][m];`   `    ``// To store the final answer` `    ``int` `ans = 0;`   `    ``// Loop to create the prefix-sum` `    ``// using two pointers` `    ``for` `(``int` `i = 0; i < n; i++)` `        ``for` `(``int` `j = 0; j < m; j++) {` `            ``if` `(j == 0) {` `                ``pre[i][j] = 1;` `                ``continue``;` `            ``}` `            ``if` `(arr[i][j] > arr[i][j - 1])` `                ``pre[i][j] = pre[i][j - 1] + 1;` `            ``else` `                ``pre[i][j] = 1;` `        ``}`   `    ``// For each column run the loop` `    ``for` `(``int` `j = 0; j < m; j++) {`   `        ``// Find the largest row-wise sorted arrays` `        ``for` `(``int` `i = 0; i < n; i++) {` `            ``int` `k = i + 1;` `            ``vector<``int``> q;` `            ``q.push_back(pre[i][j]);` `            ``while` `(k < n and arr[k] > arr[k - 1])` `                ``q.push_back(pre[k][j]), k++;`   `            ``// Applying the largest area` `            ``// under the histogram` `            ``ans = max(ans, histo(q));` `            ``i = k - 1;` `        ``}` `    ``}`   `    ``// Return the final answer` `    ``return` `ans;` `}`   `// Driver code` `int` `main()` `{` `    ``vector > arr = { { 1, 2, 3 },` `                                 ``{ 4, 5, 6 },` `                                 ``{ 1, 2, 3 } };`   `    ``cout << findLargest(arr);`   `    ``return` `0;` `}`

## Java

 `// Java implementation of the approach ` `import` `java.io.*;` `import` `java.util.*;` `class` `GFG` `{`   `  ``// Function to return the largest ` `  ``// area under a histogram` `  ``static` `int` `histo(ArrayList q)` `  ``{`   `    ``// Stack ` `    ``Stack q1 = ``new` `Stack(); `   `    ``// Length of the vector ` `    ``int` `n = q.size(); `   `    ``// Function to store the next smaller ` `    ``// and previous smaller index` `    ``int``[] pre_smaller = ``new` `int``[q.size()];` `    ``int``[] next_smaller = ``new` `int``[q.size()];`   `    ``// Finding the next smaller ` `    ``for` `(``int` `i = ``0``; i < n; i++)` `    ``{` `      ``pre_smaller[i] = -``1``;` `      ``next_smaller[i] = n; ` `    ``}` `    ``for` `(``int` `i = ``0``; i < n; i++) ` `    ``{` `      ``while` `(q1.size() > ``0` `&& q.get(q1.peek()) > q.get(i))` `      ``{` `        ``next_smaller[q1.peek()] = i;` `        ``q1.pop();` `      ``}` `      ``q1.push(i); ` `    ``}`   `    ``// Finding the previous smaller element` `    ``while` `(q1.size() > ``0``)` `    ``{` `      ``q1.pop(); ` `    ``}` `    ``for` `(``int` `i = n - ``1``; i >= ``0``; i--)` `    ``{` `      ``while` `(q1.size() > ``0` `&& q.get(q1.peek()) > q.get(i))` `      ``{` `        ``pre_smaller[q1.peek()] = i;` `        ``q1.pop(); ` `      ``}` `      ``q1.push(i); ` `    ``}`   `    ``// To store the final answer` `    ``int` `ans = ``0``; `   `    ``// Finding the final answer` `    ``for` `(``int` `i = ``0``; i < n; i++)` `    ``{` `      ``ans = Math.max(ans, (next_smaller[i] - ` `                           ``pre_smaller[i] - ``1``) * ` `                     ``q.get(i)); `   `    ``}`   `    ``// Returning the final answer` `    ``return` `ans; ` `  ``}`   `  ``// Function to return the largest area ` `  ``// for the required submatrix ` `  ``static` `int` `findLargest(ArrayList> arr) ` `  ``{`   `    ``// n and m store the number of ` `    ``// rows and columns respectively` `    ``int` `n = arr.size();` `    ``int` `m = arr.get(``0``).size();`   `    ``// To store the prefix_sum ` `    ``int``[][] pre=``new` `int``[n][m];`   `    ``// To store the final answer ` `    ``int` `ans = ``0``; `   `    ``// Loop to create the prefix-sum ` `    ``// using two pointers` `    ``for` `(``int` `i = ``0``; i < n; i++) ` `    ``{` `      ``for` `(``int` `j = ``0``; j < m; j++)` `      ``{` `        ``if` `(j == ``0``)` `        ``{` `          ``pre[i][j] = ``1``; ` `          ``continue``; ` `        ``}` `        ``if``(arr.get(i).get(j) > arr.get(i).get(j - ``1``))` `        ``{` `          ``pre[i][j] = pre[i][j - ``1``] + ``1``; ` `        ``}` `        ``else` `        ``{` `          ``pre[i][j] = ``1``;` `        ``}` `      ``}` `    ``}`   `    ``// For each column run the loop ` `    ``for` `(``int` `j = ``0``; j < m; j++)` `    ``{`   `      ``// Find the largest row-wise sorted arrays ` `      ``for` `(``int` `i = ``0``; i < n; i++)` `      ``{` `        ``int` `k = i + ``1``; ` `        ``ArrayList q = ``new` `ArrayList();` `        ``q.add(pre[i][j]);` `        ``while` `(k < n && arr.get(k).get(``0``) > arr.get(k - ``1``).get(``0``)) ` `        ``{` `          ``q.add(pre[k][j]);` `          ``k++;` `        ``}`   `        ``// Applying the largest area ` `        ``// under the histogram ` `        ``ans = Math.max(ans, histo(q));` `        ``i = k - ``1``; ` `      ``}` `    ``}`   `    ``// Return the final answer ` `    ``return` `ans; ` `  ``}`   `  ``// Driver code ` `  ``public` `static` `void` `main (String[] args) ` `  ``{` `    ``ArrayList> arr = ``new` `ArrayList>();` `    ``arr.add(``new` `ArrayList(Arrays.asList(``1``, ``2``, ``3` `)));` `    ``arr.add(``new` `ArrayList(Arrays.asList(``4``, ``5``, ``6` `)));` `    ``arr.add(``new` `ArrayList(Arrays.asList(``1``, ``2``, ``3` `)));` `    ``System.out.println(findLargest(arr));` `  ``}` `}`   `// This code is contributed by avanitrachhadiya2155`

## Python3

 `# Python3 implementation of the approach`   `# Function to return the largest` `# area under a histogram` `def` `histo(q):`   `    ``# Stack` `    ``q1 ``=` `[]`   `    ``# Length of the vector` `    ``n ``=` `len``(q)`   `    ``# Function to store the next smaller` `    ``# and previous smaller index` `    ``pre_smaller ``=` `[``0` `for` `i ``in` `range``(``len``(q))]` `    ``next_smaller ``=` `[``0` `for` `i ``in` `range``(``len``(q))]`   `    ``# Finding the next smaller` `    ``for` `i ``in` `range``(n):` `        ``pre_smaller[i] ``=` `-``1` `        ``next_smaller[i] ``=` `n` `    ``for` `i ``in` `range``(n):` `        ``while` `(``len``(q1) > ``0` `and` `q[q1[``-``1``]] > q[i]):` `            ``next_smaller[q1[``-``1``]] ``=` `i` `            ``del` `q1[``-``1``]` `        ``q1.append(i)`     `    ``# Finding the previous smaller element` `    ``while` `(``len``(q1) > ``0``):` `        ``del` `q1[``-``1``]`   `    ``for` `i ``in` `range``(n ``-` `1``, ``-``1``, ``-``1``):` `        ``while` `(``len``(q1) > ``0` `and` `q[q1[``-``1``]] > q[i]):` `            ``pre_smaller[q1[``-``1``]] ``=` `i` `            ``del` `q1[``-``1``]`   `        ``q1.append(i)`   `    ``# To store the final answer` `    ``ans ``=` `0`   `    ``# Finding the final answer` `    ``for` `i ``in` `range``(n):` `        ``ans ``=` `max``(ans, (next_smaller[i]``-` `pre_smaller[i] ``-` `1``)``*` `q[i])`   `    ``# Returning the final answer` `    ``return` `ans`   `# Function to return the largest area` `# for the required submatrix` `def` `findLargest(arr):` `    `  `    ``# n and m store the number of` `    ``# rows and columns respectively` `    ``n ``=` `len``(arr)` `    ``m ``=` `len``(arr[``0``])`   `    ``# To store the prefix_sum` `    ``pre ``=` `[[``0` `for` `i ``in` `range``(m)] ``for` `i ``in` `range``(n)]`   `    ``# To store the final answer` `    ``ans ``=` `0`   `    ``# Loop to create the prefix-sum` `    ``# using two pointers` `    ``for` `i ``in` `range``(n):` `        ``for` `j ``in` `range``(m):` `            ``if` `(j ``=``=` `0``):` `                ``pre[i][j] ``=` `1` `                ``continue`   `            ``if` `(arr[i][j] > arr[i][j ``-` `1``]):` `                ``pre[i][j] ``=` `pre[i][j ``-` `1``] ``+` `1` `            ``else``:` `                ``pre[i][j] ``=` `1`     `    ``# For each column run the loop` `    ``for` `j ``in` `range``(m):`   `        ``# Find the largest row-wise sorted arrays` `        ``for` `i ``in` `range``(n):` `            ``k ``=` `i ``+` `1` `            ``q ``=` `[]` `            ``q.append(pre[i][j])` `            ``while` `(k < n ``and` `arr[k] > arr[k ``-` `1``]):` `                ``q.append(pre[k][j])` `                ``k ``+``=` `1`   `            ``# Applying the largest area` `            ``# under the histogram` `            ``ans ``=` `max``(ans, histo(q))` `            ``i ``=` `k ``-` `1`   `    ``# Return the final answer` `    ``return` `ans`   `# Driver code`   `arr ``=` `[ [ ``1``, ``2``, ``3` `],` `    ``[ ``4``, ``5``, ``6` `],` `    ``[ ``1``, ``2``, ``3` `] ]`   `print``(findLargest(arr))`   `# This code is contributed by mohit kumar 29`

## C#

 `// C# implementation of the approach ` `using` `System;` `using` `System.Collections.Generic;`   `class` `GFG{` `    `  `// Function to return the largest ` `// area under a histogram` `static` `int` `histo(List<``int``> q)` `{` `    `  `    ``// Stack` `    ``Stack<``int``> q1 = ``new` `Stack<``int``>();` `    `  `    ``// Length of the vector ` `    ``int` `n = q.Count;` `    `  `    ``// Function to store the next smaller ` `    ``// and previous smaller index` `    ``int``[] pre_smaller = ``new` `int``[q.Count];` `    ``int``[] next_smaller = ``new` `int``[q.Count];` `    `  `    ``// Finding the next smaller` `    ``for``(``int` `i = 0; i < n; i++)` `    ``{` `        ``pre_smaller[i] = -1;` `        ``next_smaller[i] = n; ` `    ``}` `    ``for``(``int` `i = 0; i < n; i++)` `    ``{` `        ``while` `(q1.Count > 0 && q[q1.Peek()] > q[i])` `        ``{` `            ``next_smaller[q1.Peek()] = i;` `            ``q1.Pop();` `        ``}` `        ``q1.Push(i);` `    ``}` `    `  `    ``// Finding the previous smaller element` `    ``while` `(q1.Count > 0)` `    ``{` `        ``q1.Pop(); ` `    ``}` `    `  `    ``for``(``int` `i = n - 1; i >= 0; i--)` `    ``{` `        ``while` `(q1.Count > 0 && q[q1.Peek()] > q[i])` `        ``{` `            ``pre_smaller[q1.Peek()] = i;` `            ``q1.Pop(); ` `        ``}` `        ``q1.Push(i);` `    ``}` `    `  `    ``// To store the final answer` `    ``int` `ans = 0; ` `    `  `    ``// Finding the final answer` `    ``for``(``int` `i = 0; i < n; i++)` `    ``{` `        ``ans = Math.Max(ans, (next_smaller[i] - ` `                              ``pre_smaller[i] - 1) * q[i]);` `    ``}` `    `  `    ``// Returning the ` `    ``// final answer` `    ``return` `ans; ` `}`   `// Function to return the largest area ` `// for the required submatrix ` `static` `int` `findLargest(List> arr)` `{` `    `  `    ``// n and m store the number of ` `    ``// rows and columns respectively` `    ``int` `n = arr.Count;` `    ``int` `m = arr[0].Count;` `    `  `    ``// To store the prefix_sum ` `    ``int``[,] pre = ``new` `int``[n, m];` `    `  `    ``// To store the final answer ` `    ``int` `ans = 0;` `    `  `    ``// Loop to create the prefix-sum ` `    ``// using two pointers` `    ``for``(``int` `i = 0; i < n; i++) ` `    ``{` `        ``for``(``int` `j = 0; j < m; j++)` `        ``{` `            ``if` `(j == 0)` `            ``{` `                ``pre[i, j] = 1; ` `                ``continue``; ` `            ``}` `            `  `            ``if` `(arr[i][j] > arr[i][j - 1])` `            ``{` `                ``pre[i, j] = pre[i,j - 1] + 1; ` `            ``}` `            ``else` `            ``{` `                ``pre[i, j] = 1;` `            ``}` `        ``}` `    ``}` `    `  `    ``// For each column run the loop ` `    ``for``(``int` `j = 0; j < m; j++)` `    ``{` `        `  `        ``// Find the largest row-wise sorted arrays ` `        ``for``(``int` `i = 0; i < n; i++)` `        ``{` `            ``int` `k = i + 1; ` `            ``List<``int``> q = ``new` `List<``int``>();` `            ``q.Add(pre[i, j]);` `            `  `            ``while``(k < n && arr[k][0] > arr[k - 1][0])` `            ``{` `                ``q.Add(pre[k, j]);` `                ``k++;` `            ``}` `            `  `            ``// Applying the largest area ` `            ``// under the histogram` `            ``ans = Math.Max(ans, histo(q));` `            ``i = k - 1; ` `        ``}` `    ``}` `    `  `    ``// Return the final answer` `    ``return` `ans; ` `}`   `// Driver code ` `static` `public` `void` `Main()` `{` `    ``List> arr = ``new` `List>();` `    ``arr.Add(``new` `List<``int``>(){1, 2, 3});` `    ``arr.Add(``new` `List<``int``>(){4, 5, 6 });` `    ``arr.Add(``new` `List<``int``>(){1, 2, 3});` `    `  `    ``Console.WriteLine(findLargest(arr));` `}` `}`   `// This code is contributed by rag2127`

## Javascript

 ``

Output:

`6`

Time Complexity: O(N*N), as we are using nested loops to traverse N*N times.

Auxiliary Space: O(N*N), as we are using extra space for matrix.