85 最大矩形

19 篇文章 0 订阅
5 篇文章 0 订阅

题目

给定一个仅包含 0 和 1 、大小为 rows x cols 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。

示例 1:

输入:matrix = [[“1”,“0”,“1”,“0”,“0”],[“1”,“0”,“1”,“1”,“1”],[“1”,“1”,“1”,“1”,“1”],[“1”,“0”,“0”,“1”,“0”]]
输出:6
解释:最大矩形如上图所示。
示例 2:

输入:matrix = []
输出:0
示例 3:

输入:matrix = [[“0”]]
输出:0
示例 4:

输入:matrix = [[“1”]]
输出:1
示例 5:

输入:matrix = [[“0”,“0”]]
输出:0

  • 法一:对矩阵的每一列,查找柱状图中的最大矩形
class Solution {
public:
    int maximalRectangle(vector<vector<char>>& matrix) {
        int m=matrix.size(),n=matrix[0].size();//记录矩阵的长和宽
        vector<int> height(n,0);//存储以当前行为下边界,每一列的高度(从当前行向上数连续1的个数)
        //当前行开始连续1的个数,实际上为上一行对应位置的数字加上当前行的判断。如果当前行对应位置为0,则为0;如果为1,则为上一行对应位置个数加1
        int result=0;
        for(int i=0;i<m;i++)
        {
        	//以每一行为坐标轴,计算当前当前行及以上位置,柱状图中的最大矩形面积
        	//for循环确定柱状图中每个位置的高度
            for(int j=0;j<n;j++)
            {
                if(matrix[i][j]=='1')
                {
                    height[j]++;
                }else height[j]=0;
            }
            //确定当前行及以上的最大矩形面积
            result = max(result, maxRectangle(height));
        }

        return result;
    }
	
	//确定当前行及以上的最大矩形面积
    int maxRectangle(const vector<int>& height)
    {
        stack<int> index;//栈,存储height数组的下标
        int result=0;//最大矩形面积
        int n=height.size();
        //遍历数组,计算以每一个数字为高时的最大矩形面积,在其中取最大值
        for(int i=0;i<n;i++)
        {	
        	//如果栈非空,且当前元素的高度小于栈顶元素高度,则栈顶元素找到了右边界,此时计算矩形高度
        	//栈顶元素的左边界就是栈中的倒数第二个元素
            while(!index.empty()&&height[i]<height[index.top()])
            {
                int he=height[index.top()];//记录当前矩形高度
                index.pop();//弹栈
                int len=i;//记录当前矩形宽
                if(!index.empty()) len=i-index.top()-1;
                result=max(result,he*len);
            }
            index.push(i);
        }
        //此时i已经遍历全部数组,栈中剩余元素单调递增,且右边界均为n。计算矩形面积,更新最大值
        while(!index.empty())
        {
            int he=height[index.top()];
            index.pop();
            if(index.empty()) result=max(result,he*n);
            else result=max(result,he*(n-index.top()-1));
        }
        return result;
    }

};
  • 时间复杂度O(mn)

  • 空间复杂度O(n)

  • 思路

    • 将求矩阵中的最大矩形面积,转化为,固定横轴求柱状图中的最大矩形面积
    • 求当前横轴对应的柱状图高度:如果当前行该位置的元素为0,则高度为0.如果当前行该位置的元素为1,则高度为上一行该位置高度加一
    • 求柱状图中最大矩形面积函数解析:https://blog.csdn.net/weixin_45781228/article/details/119894579
  • 法一:代码优化,在height数组的首尾添加哨兵


class Solution {
public:
    int maximalRectangle(vector<vector<char>>& matrix) {
        int m=matrix.size(),n=matrix[0].size();
        vector<int> height(n,0);
        int result=0;
        for(int i=0;i<m;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(matrix[i][j]=='1')
                {
                    height[j]++;
                }else height[j]=0;
            }
            result = max(result, maxRectangle(height));
        }

        return result;
    }
	//在height数组的首尾添加哨兵0,计算矩形长度时不用判断栈空
    int maxRectangle(const vector<int>& height)
    {
        stack<int> index;
        int result=0;
        vector<int> height2(height);
        height2.push_back(0);
        height2.insert(height2.begin(),0);
        int n=height2.size();
        index.push(0);
        for(int i=1;i<n;i++)
        {
            while(!index.empty()&&height2[i]<height2[index.top()])
            {
                int he=height2[index.top()];
                index.pop();
                int len=i-index.top()-1;
                result=max(result,he*len);
            }
            index.push(i);
        }
        return result;
    }

};
  • 法二:动态规划
class Solution {
public:
    int maximalRectangle(vector<vector<char>>& matrix) {
        if(matrix.empty()) return 0;//去除矩阵为空的情况
        int m=matrix.size(),n=matrix[0].size();
        //H[i]表示当前行i处矩形对应的高,L[i]表示当前左边离i处最近的字符0的下标,R[i]表示当前右边离i处最近的字符0的下标
        //为了避免边界问题导致出错,选择L数组中-1作为标志位,选择R数组中n作为标志位
        vector<int> H(n,0),L(n,-1),R(n,n);
        int result=0;//记录当前的最大矩形面积
		//每一层for循环记录当前行及以上的最大矩形面积
        for(int i=0;i<m;i++)
        {
            int left=-1,right=n;//left为当前已经访问过的字符中最右边0对应的下标,right为从右往左访问过的字符中最左边0对应的下标
            //填L数组和H数组,从左往右遍历当前行
            for(int j=0;j<n;j++)
            {
                if(matrix[i][j]=='1')//如果为1,当前位置矩形的高度为上一行高度加1,距离当前位置最近的0的下标为上一行当前位置最近的0和left,二者取较大值
                {
                    H[j]++;
                    L[j]=max(L[j],left);
                }else{//如果为0,更新left的值,当前位置的矩形高度为0,距离当前位置最近的0的下标置为标志位
                    left=j;
                    H[j]=0;L[j]=-1;
                }
            }
            //填R数组然后计算当前矩形的面积
            for(int j=n-1;j>=0;j--)
            {
                if(matrix[i][j] == '1')//如果当前数字为1,更新R数组,计算矩形面积
                {
                    R[j]=min(R[j],right);
                    result=max(result,H[j]*(R[j]-L[j]-1));
                }else{//如果为0,更新right和R数组对应位置为标志位
                    right=j;
                    R[j]=n;
                }
            }
        }
        return result;
    }
};
  • 时间复杂度O(mn)
  • 空间复杂度O(n)
  • 思路
    • 动态规划。采用三个数组,H记录当前位置矩形的高,L记录当前位置矩形左边界,R记录当前位置矩形的右边界
    • 当前行的数据可以使用上一行的数据。当前行H的值,如果字符为1就是上一行对应位置的值加一。当前行L的值就是上一行对应位置L的值与left取较大者。当前行R的值就是上一行对应位置R的值与right取较小者
    • 详细查看代码注释
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值