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

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’.
    • Initialise ‘i’ equals 0.
    • Run a loop on ‘i’ while ‘i’ is less than ‘N’
      • Initialise ‘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 approah:

CPP

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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 requried 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;
}

chevron_right


Python

filter_none

edit
close

play_arrow

link
brightness_4
code

# Pythono3 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 requried 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

chevron_right


Output:

6

Time Complexity: O(N2)

Don’t stop now and take your learning to the next level. Learn all the important concepts of Data Structures and Algorithms with the help of the most trusted course: DSA Self Paced. Become industry ready at a student-friendly price.




My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.



Improved By : mohit kumar 29