力扣算法学习day41-3

力扣算法学习day41-3

84-柱状图中最大的矩形

题目

image-20220303234748355

image-20220303234812579

代码实现

class Solution {
    public int largestRectangleArea(int[] heights) {
        // 代码随想录刷题收官之战!速度:21ms
        // 首先,比较容易想到双指针思路,就是求每个柱子为中心凹点的最大矩形面积。那么需要从左到右
        // 遍历柱子,然后每个柱子还需要遍历找它左边第一个小于它的位置,和右边第一个小于它的位置。
        // 双指针很明显时间复杂度是O(n^2),然后感觉用dp优化,很容易想到的就是dp优化双指针需要遍历
        // 的时候去找左右第一个小于的值,而这个值可以由dp数组先求得,但是实际操作我发现这个dp数组
        // 两个也是需要双重循环的估计速度差不多,就算了。
        // 然后速度优化 考虑使用单调栈(单调减,从栈顶到栈底 一次降低)(注:这里栈用于存储坐标)
        // 规则:
        // 1.如果当前栈顶元素小于或等于当前比较元素,直接压入栈.
        // 2.如果当前栈顶元素大于比较元素,弹出栈顶元素,并计算栈顶元素的面积。
        // 这里的原理是遇到小于栈顶的元素,那么一定可以确定当前栈顶的左边最小和右边最小的坐标,即
        // 这里和双指针计算的原理是一样的,只是因为单调栈的性质确定了左边保存的是比它小的第一个数,
        // 而如果遇到的比较的这个数如果比栈顶小,那又确定了它的右边遇到的第一个比它小的元素。
        // 这里计算公式是:
        // 1.宽为遇到的小于栈顶元素的坐标 - 弹出后存储为mid,栈顶元素的值 - 1; 注:如果弹出后栈为空了,那
        // 直接宽 = 1。 然后面积 = 宽 * heights[mid]
        // 这里最后还需要处理留在栈中的元素。计算原理同理。
        // 这里为了方便计算需要在头尾加上0
        int[] height = new int[heights.length+2];
        for(int i = 1;i < height.length - 1;i++){
            height[i] = heights[i-1];
        }
        LinkedList<Integer> stack = new LinkedList<>();
        int result = 0;
        
        for(int i = 0;i < height.length;i++){
            while(!stack.isEmpty() && height[i] < height[stack.peek()]){
                int mid = stack.pop();

                int x = 0;// 先设置变量x为宽,下面分两种情况赋值
                if(stack.isEmpty()){
                    x = i - mid;
                } else{
                    x = i - stack.peek() - 1;
                }

                int area = x * height[mid];
                
                if(area > result){
                    result = area;
                }
            }

            stack.push(i);
        }   

        return result;

        // 额,做完了,感觉可能动态规划会更快,明天开始复习,顺便补上dp解法。
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

人山人

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

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

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

打赏作者

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

抵扣说明:

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

余额充值