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: 6
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: 4
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 <bits/stdc++.h>
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<vector<int> > 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<vector<int> > 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<Integer> q)
{
// Stack
Stack<Integer> q1 = new Stack<Integer>();
// 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<ArrayList<Integer>> 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<Integer> q = new ArrayList<Integer>();
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<ArrayList<Integer>> arr = new ArrayList<ArrayList<Integer>>();
arr.add(new ArrayList<Integer>(Arrays.asList(1, 2, 3 )));
arr.add(new ArrayList<Integer>(Arrays.asList(4, 5, 6 )));
arr.add(new ArrayList<Integer>(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<List<int>> 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<List<int>> arr = new List<List<int>>();
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
<script>
// Javascript implementation of the approach
// Function to return the largest
// area under a histogram
function histo(q)
{
// Stack
let q1 = [];
// Length of the vector
let n = q.length;
// Function to store the next smaller
// and previous smaller index
let pre_smaller = new Array(q.length);
let next_smaller = new Array(q.length);
// Finding the next smaller
for (let i = 0; i < n; i++)
{
pre_smaller[i] = -1;
next_smaller[i] = n;
}
for (let i = 0; i < n; i++)
{
while (q1.length > 0 && q[q1[q1.length-1]] > q[i])
{
next_smaller[q1[q1.length-1]] = i;
q1.pop();
}
q1.push(i);
}
// Finding the previous smaller element
while (q1.length > 0)
{
q1.pop();
}
for (let i = n - 1; i >= 0; i--)
{
while (q1.length > 0 && q[q1[q1.length-1]] > q[i])
{
pre_smaller[q1[q1.length-1]] = i;
q1.pop();
}
q1.push(i);
}
// To store the final answer
let ans = 0;
// Finding the final answer
for (let 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
function findLargest(arr)
{
// n and m store the number of
// rows and columns respectively
let n = arr.length;
let m = arr[0].length;
// To store the prefix_sum
let pre=new Array(n);
for(let i=0;i<n;i++)
{
pre[i]=new Array(m);
for(let j=0;j<m;j++)
{
pre[i][j]=0;
}
}
// To store the final answer
let ans = 0;
// Loop to create the prefix-sum
// using two pointers
for (let i = 0; i < n; i++)
{
for (let 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 (let j = 0; j < m; j++)
{
// Find the largest row-wise sorted arrays
for (let i = 0; i < n; i++)
{
let k = i + 1;
let q = [];
q.push(pre[i][j]);
while (k < n && arr[k][0] > arr[k - 1][0])
{
q.push(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
let arr=[[1, 2, 3],[4, 5, 6 ],[1, 2, 3]];
document.write(findLargest(arr));
// This code is contributed by patel2127
</script>
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.
Similar Reads
Sort the matrix row-wise and column-wise Given a n x n matrix. The problem is to sort the matrix row-wise and column wise. Examples: Input : mat[][] = { {4, 1, 3}, {9, 6, 8}, {5, 2, 7} } Output : 1 3 4 2 5 7 6 8 9 Input : mat[][] = { {12, 7, 1, 8}, {20, 9, 11, 2}, {15, 4, 5, 13}, {3, 18, 10, 6} } Output : 1 5 8 12 2 6 10 15 3 7 11 18 4 9 1
9 min read
Largest square sub-matrix with equal row, column, and diagonal sum Given a matrix mat[][] of dimensions N*M, the task is to find the size of the largest square submatrix such that the sum of all rows, columns, diagonals in that submatrix are equal.Examples:Input: N = 3, M = 4, mat[][] = [[5, 1, 3, 1], [9, 3, 3, 1], [1, 3, 3, 8]]Output: 2Explanation:The submatrix wh
11 min read
Maximum sum of any submatrix of a Matrix which is sorted row-wise and column-wise Given a matrix mat[][] whose elements are sorted both row-wise and column-wise. The task is to find the maximum sum of any submatrix from the given matrix mat[][]. Examples: Input: mat[][] = { {-6, -4, -1}, {-3, 2, 4}, {2, 5, 8}} Output: 19 Explanation: The largest submatrix is given by: 2 4 5 8Inpu
10 min read
Print all elements in sorted order from row and column wise sorted matrix Given an n x n matrix, where every row and column is sorted in non-decreasing order. Print all elements of the matrix in sorted order. Example: Input: mat[][] = { {10, 20, 30, 40}, {15, 25, 35, 45}, {27, 29, 37, 48}, {32, 33, 39, 50}, };Output: 10 15 20 25 27 29 30 32 33 35 37 39 40 45 48 50 Recomme
15+ min read
Sort the Matrix based on the given column number Given a Matrix of size M * N (0-indexed) and an integer K, the matrix contains distinct integers only, the task is to sort the Matrix (i.e., the rows of the matrix) by their Values in the Kth column, from Maximum to Minimum. Return the matrix after sorting it. Examples: Input: Matrix = [[10, 6, 9, 1
12 min read