最大01子矩阵问题(单调栈优化)

    科技2025-04-20  5

    题目描述:

    顾名思义,给定n*m大小的01矩阵,要求找到1数量最多的全1子矩阵

    题目链接:

    85. Maximal Rectangle

    问题降阶:

    思考二维问题前,先将问题降阶,思考该问题在一维状况下的解决方式会是一个比较好的思路。

    题目链接:

    485. Max Consecutive Ones

    题意:

    在01数组中寻找最长连续1的长度

    思路:

    简单的dp,维护数组中每个位置作为结尾的最长连续1长度。

    代码:

    /* Author Owen_Q */ class Solution { public: int findMaxConsecutiveOnes(vector<int>& nums) { int re = 0; int now = 0; for(int i:nums) { if(i==1) { now+=1; re = max(re,now); } else now = 0; } return re; } };

    一维转二维:

    思路:

    解决了一维的问题,对于二维问题,完全可以率先按行进行预处理,处理完后矩阵中存储的即使改行到当前位置为止的最长连续1长度。

    而为了寻找最大全1矩阵,完全可以遍历每个位置,以预处理的长度作为第一行,分别向上下下找到第一个小于该长度的行,中间的所有行即可用于形成全1矩阵。于是整理复杂度为

    代码:

    /* Author Owen_Q */ class Solution { public: int maximalRectangle(vector<vector<char>>& matrix) { int n,m; n = matrix.size(); if(n==0) return 0; m = matrix[0].size(); for(int i=0;i<n;i++) { for(int j=0;j<m;j++) { matrix[i][j] -= '0'; if(j>0&&matrix[i][j]>0) matrix[i][j] += matrix[i][j-1]; cout << (int)matrix[i][j] << " "; } cout << endl; } int re = 0; for(int i=0;i<n;i++) { for(int j=0;j<m;j++) { int pos0 = i-1; while(pos0>=0&&matrix[pos0][j]>=matrix[i][j]) pos0--; int pos1 = i+1; while(pos1<n&&matrix[pos1][j]>=matrix[i][j]) pos1++; re = max(re,matrix[i][j]*(pos1-pos0-1)); } } return re; } };

    单调栈优化:

    思路:

    看到寻找下一个长度更短的行,立刻想到单调栈优化,即可将复杂度降到

    至于具体优化策略,则需要整体思路的转化。

    相较于原来向上下分别寻找,这次只需要向下维护一个单调栈,每次当元素出栈时,即可利用出栈的行长构造一个全1矩阵。最后将栈清空即可得到最优结果。

    构造时以出栈元素为横向边长,以目前栈顶到当前元素的距离为纵向边长即可完成

    代码:

    /* Author Owen_Q */ class Solution { public: int maximalRectangle(vector<vector<char>>& matrix) { int n,m; n = matrix.size(); if(n==0) return 0; m = matrix[0].size(); for(int i=0;i<n;i++) { for(int j=0;j<m;j++) { matrix[i][j] -= '0'; if(j>0&&matrix[i][j]>0) matrix[i][j] += matrix[i][j-1]; cout << (int)matrix[i][j] << " "; } cout << endl; } int re = 0; for(int j=0;j<m;j++) { stack<int> st; for(int i=n-1;i>=0;i--) { while((!st.empty())&&(matrix[st.top()][j]>=matrix[i][j])) { int now = st.top(); st.pop(); int len; if(st.empty()) len = n; else len = st.top(); re = max(re,matrix[now][j]*(len-i-1)); } st.push(i); } while(!st.empty()) { int now = st.top(); st.pop(); int len; if(st.empty()) len = n; else len = st.top(); re = max(re,matrix[now][j]*len); } cout << re << endl; } return re; } };

     

     

    Processed: 0.012, SQL: 8