LeetCode HOT 100 —— 85.最大矩阵

题目

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

思路

前缀和+单调栈

本题把每一层看成是一个柱状图,可以转化成代码随想录——柱状图中最大的矩形(双指针&动态规划&单调栈)

如下图的橙色部分,就可以完全转化成柱状图中最大的矩形
在这里插入图片描述
每一层看作是柱状图,注意:一定要是连续的1

第一层柱状图的高度[“1”,“0”,“1”,“0”,“0”],最大面积为1;

第二层柱状图的高度[“2”,“0”,“2”,“1”,“1”],最大面积为3;

第三层柱状图的高度[“3”,“1”,“3”,“2”,“2”],最大面积为6;

第四层柱状图的高度[“4”,“0”,“0”,“3”,“0”],最大面积为4(这里要注意,因为第1列和第2列遇到了0,没有之前的1不会继续统计);

接下来只需要求出每一层的height[i]然后传递给柱状图中最大的矩形中的函数即可

java代码如下:

//单调栈 + 哨兵模式
class Solution {
	public int maximalRectangle(char[][] matrix){
		int col = matrix[0].length; 
		int[] height = new int[col + 2];//申请一个新数组,长度是矩阵的列数+2,分别头尾补0,即两个哨兵,数组的内容记录的是每一层的高度
		//在左右两侧添加两个哨兵
		height[0] = 0;//左侧的哨兵使得不用判空
		height[col + 1] = 0;//右侧的哨兵能够保证在遍历结束时弹出前面的柱子计算面积
		Stack<Integer> stack = new Stack<>();
		int maxArea = 0;//记录最大面积
		for(int row = 0; row < matrix.length; row++){//遍历矩阵中的每一行元素
			for(int i = 0; i < col; i++){//遍历列
				if (matrix[row][i] == '1'){//如果当前元素是1,那么当前列的高度+1
					height[i + 1]++;//因为首位置的哨兵height[0]已经添加过了,所以需要填充的范围是[1,col],所以要用i+1,进行填充,同时这里是统计第row行的每列的高度,然后下一行row+1行继续循环的时候,遍历到相同列会进行累加,最终得到每列的最终高度
				} else {//如果当前元素是0,那么高度直接置为0(之前有多少个1都没用,因为不连续了)
					height[i + 1] = 0;
				}
			}
			maxArea = Math.max(maxArea,largestRectangleArea(height));//将求出来的高度,传递给柱状图中最大矩形的那个算法中
		}
		return maxArea;
	}
	
	public int largestRectangleArea(int[] height){//本题相当于是这一步的heigh不再由题目给出,而是自己写个函数求出来,并作为参数传递进来
		Stack<Integer> stack = new Stack<Integer>();
		
		//数组扩容,头尾各加一个元素,哨兵模式
		int[] newHeight = new int[height.length + 2];
		newHeight[0] = 0; //左侧的哨兵使得不用判空
		newHeight[newHeight.length -1] = 0;//右侧的哨兵能够保证在遍历结束时弹出前面的柱子计算面积
		for(int i = 0; i < height.length; i++){
			newHeight[i + 1] = height[i];
		}
		height = newHeight;
		stack.push(0);
		int result = 0;
		for(int i = 1; i < height.length; i++){
			if(height[i] >= height[stack.peek()]){
				stack.push(i);
			}  else {
				while(!stack.isEmpty() && height[i] < height[stack.peek()]){
					int mid = stack.pop();
					int left = stack.peek();
					result = Math.max(result, height[mid] * (i - left - 1));
				}
				stack.push(i);
			}
		}
		return result;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HDU-五七小卡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值