LeetCode之团灭单调栈:深入解析与高效解题技巧

目录

主干题

题目描述

解题思路

代码示例

Java版代码 

Python版代码 

变形题

题目一

题目二

题目三

题目四

解法一

解法二

题目五

参考文章

相似题目


主干题

力扣085最大子矩形

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

示例:

输入:
[
  ["1","0","1","0","0"],
  ["1","0","1","1","1"],
  ["1","1","1","1","1"],
  ["1","0","0","1","0"]
]
输出: 6

解题思路

1、计算每个行和前面所有行叠加所产生的数组里的最大子矩阵,求出最大的数组里的最大子矩阵。叠加规则为遇到1累加,遇到0重新开始计算

2、数组的最大子矩阵实际就是求以j为中心向左右寻找第一个比j柱子小的柱子,然后计算对应的矩形面积后比较大小

如何求arr[j]数组的最大矩形大小

求数组最大矩形大小,我们是利用一个单调栈来实现的。单调栈顾名思义就是栈的元素从栈底到栈顶依次是递增或递减的。利用单调递增栈我们可以求出数组中每一个元素左边离它最近比它小的位置和右边离它最近比它小的位置在哪里。例如对于数组{3,1,3,2,2}对于第一个元素左边离它最近比它小的位置为空,右边离它最近比它小的位置在哪里为1。如何利用单调递增栈实现上述过程呢?在将数组元素压入栈时需要遵循下面的规则:

  1. 如果当前栈stack为空或者当前数组的元素arr[j]>arr[stack.top()](栈顶元素),那么直接把当前元素的位置j压入stack。
  2. 如果当前栈不为空且当前数组元素arr[j]<=arr[stack.top()](栈顶元素),那么依次从stack弹出元素,并结算栈顶元素为根基,向左和向右分别可以拓展到哪里,则可以得出当前最大子矩阵的大小为多少。

计算最大矩阵大小思想如下:

如何当前遍历的元素的元素为i,当前栈顶元素元素为j,弹出栈顶元素后,新的栈顶元素为k。那么现在考虑以元素为j为根基,其向左最左能达到k+1,因为j最左最近小于j的元素应该为k,那么向右最远应该能到i-1,因为j之所以被弹出,就是因为遇到了第一个比位置j值小的位置。所以其最大子矩阵大小结算为(i-k-1)*height[j].

代码示例

Java版代码 

class Solution {
  

    public int maximalRectangle(char matrix[][]) {
 
		int arr[] = new int[matrix[0].length];
 
		Integer maxSum = 0;
		for (int i = 0; i < matrix.length; i++) {
			for (int j = 0; j < matrix[0].length; j++) {
				arr[j] = (matrix[i][j] == '0' ? 0 : arr[j] + 1);
			}
			maxSum = Math.max(maxSum, getArrMaxSum(arr));
		}
 
		return maxSum;
	}
 
	private int getArrMaxSum(int[] arr) {

		Stack<Integer> stack = new Stack();
		Integer j = null;
		Integer k = -1;
		int max = 0;
		for (int i = 0; i < arr.length; i++) {
 
            if(stack.isEmpty() || arr[stack.peek()] < arr[i]){
                stack.push(i);
            }else{

                while (!stack.isEmpty() && arr[stack.peek()] >= arr[i]) {
                    j =  stack.pop();
                    k =  stack.isEmpty()? -1:stack.peek();
                    max = Math.max(max, ((i - 1) - (k + 1) + 1) * arr[j]);
                }
                stack.push(i);
            }
		}
        //i=arr.length - 1 仍然需要计算栈内剩余数据所构成的组合情况
		while (!stack.isEmpty()) {
			j = stack.pop();
			k = stack.isEmpty() ? -1 : stack.peek();
			max = Math.max(max, ((arr.length - 1) - (k + 1) + 1) * arr[j]);
		}
 

		return max;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

数据与算法架构提升之路

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

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

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

打赏作者

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

抵扣说明:

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

余额充值