📌  相关文章
📜  最大的按行和按列排序的子矩阵

📅  最后修改于: 2022-05-13 01:57:09.147000             🧑  作者: Mango

最大的按行和按列排序的子矩阵

给定一个N * M矩阵mat[][] ,任务是找到面积最大的矩形子矩阵,使得子矩阵的每一列和每一行都严格递增。

例子:

方法:有很多方法可以解决这个问题,从 O(N 3 * M 3 ) 到 O(N * M)。在本文中,将讨论使用堆栈的具有 O(N * M) 时间复杂度的方法。
在继续之前,建议解决此问题。问题。

让我们尝试广泛地理解该方法,然后将讨论该算法。对于矩阵的每一列,尝试找到在该列具有左边缘的最大的按行和按列排序的子矩阵。要执行相同的操作,请创建一个矩阵pre[][]其中pre[i][j]将存储从数组arr[i]的索引j开始的最长递增子数组的长度。
现在使用这个矩阵,对于每一列j ,找到最长的行和列排序数组的长度。要处理一列,将需要数组pre[][j]的所有递增子段。使用两指针技术也可以找到相同的结果。在这些子段中的每一个中,只需将逐行增加的子段视为条形,即可找到直方图下的最大区域。

  • 为每一行“i”创建一个前缀和数组,该数组存储在该行的每一列“j”处结束的最大递增子数组的长度。
  • 一旦我们有了这个数组,对于每一列'j'。
    • 初始化 'i' 等于 0。
    • 在“i”小于“N”时在“i”上运行循环
      • 初始化 'k' 等于 i+1。
      • 当 k 小于 N 且 arr[k][j] 大于 arr[k-1][j] 时,增加 k。
      • 将子数组 pre[i][j] 上的直方图问题应用到 pre[k-1][j] 上,找到它下面的最大区域。让我们将此值称为“V”。将最终答案更新为 ans = max(ans, val)。
      • 更新 'i' 等于 k-1。

下面是上述方法的实现:

C++
// C++ implementation of the approach
#include 
using namespace std;
 
// Function to return the largest
// area under a histogram
int histo(vector q)
{
 
    // Stack
    stack 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 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 q)
{
     
    // Stack
    Stack q1 = new Stack();
     
    // 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 q = new List();
            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(){1, 2, 3});
    arr.Add(new List(){4, 5, 6 });
    arr.Add(new List(){1, 2, 3});
     
    Console.WriteLine(findLargest(arr));
}
}
 
// This code is contributed by rag2127


Javascript


输出:
6

时间复杂度: O(N 2 )
辅助空间:O(N 2 )。