LeetCode:84.柱状图中最大的矩形

84.柱状图中最大的矩形

题目

给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。
在这里插入图片描述
在这里插入图片描述

单调栈(单调递减)

思路

mid作为中间值的条件,以 mid 左边最小的值为 left ,以 mid 右边最小的值为 right ,减去 left 和 right 两边的值,取 left 和 right 中间所包含的最大面积。

  • 栈的执行过程:
    • 当遍历的值比栈口元素的值小时,获取 left , right , mid 的值
    • 当遍历的值比栈口元素的值大时,将其压栈
  • 为何将数组首尾添加 0 ?
    • 当数组元素形成递增的值时,如:[1, 2, 3, 4],压栈之后形成:[4, 3, 2, 1]每个遍历的元素都比栈口的元素大,则不能寻找到最小的值,在末尾添加 0 ,可以在执行到 0 时,获取 left , right , mid 的值
      在这里插入图片描述

    • 当数组元素形成递减的值时,如:[4, 3, 2, 1],压栈之后形成:[1, 2, 3, 4]每个遍历的元素都比栈口的元素小,则执行程序,但在获取 left , right , mid 的值时,则无法获取,当栈口为 4 ,遍历元素为 3 ,那么 mid = 4 , right = 3 , left = ? ,所以在数组头部加上 0 ,能让 left 获取到值
      在这里插入图片描述

class Solution {
    public int largestRectangleArea(int[] heights) {
        // 计算最终结果
        int res = 0;
        // +2是为了在数组首尾加0,方便之后的操作
        int[] newHeights = new int[heights.length + 2];
        newHeights[0] = 0;
        newHeights[newHeights.length - 1] = 0;

        // 将heights数组中元素加入到newHeights数组,从下标为1开始
        for(int i = 0; i < heights.length; i++){
            newHeights[i + 1] = heights[i];
        }
        // 将heights数组替代为newHeights数组
        heights = newHeights;

        Stack<Integer> stack = new Stack<>();
        // 将下标0的元素压栈
        stack.push(0);
        // 下标0已压栈,从下标1开始
        for(int i = 1; i < heights.length; i++){
            // 单调递减,所以heights元素的值比栈中的值大时,压栈
            if(heights[i] > heights[stack.peek()]){
                stack.push(i);
            // heights元素的值与栈中的值相等时,也就是有了重复值,可以选择弹出再压栈,也可以直接压栈
            }else if(heights[i] == heights[stack.peek()]){
                stack.pop(); // 加不加都可以
                stack.push(i);
            // heights元素的值比栈中的值小时,符合单调递减的情况
            }else{
                while(!stack.isEmpty() && heights[i] < heights[stack.peek()]){
                    // 获取当时的栈顶元素
                    int middle = stack.peek();
                    // 将其弹出
                    stack.pop();
                    // 获取下一个栈顶元素
                    int left = stack.peek();
                    // 标记已经遍历到的位置
                    int right = i;
                    // 计算宽度
                    int w = right - left - 1;
                    // 计算高度
                    int h = heights[middle];
                    res = Math.max(res, w * h);
                }
                stack.push(i);
            }
        }
        return res;
    }
}

单调栈(精简)

class Solution {
    public int largestRectangleArea(int[] heights) {
        int res = 0;
        int[] newHeights = new int[heights.length + 2];
        newHeights[0] = 0;
        newHeights[newHeights.length - 1] = 0;

        /*
        数组扩容方法:System.arraycopy();需要5个参数:
            1. 拷贝源(要拷贝的数组)
            2. 拷贝源中需要从哪拷贝的下标位置
            3. 目标源(拷贝到哪里的数组)
            4. 目标源中需要放置在哪个位置的下标位置
            5. 需要拷贝的长度
         */
        System.arraycopy(heights, 0, newHeights, 1, heights.length);
        Stack<Integer> stack = new Stack<>();
        stack.push(0);
        for(int i = 1; i < newHeights.length; i++){
                while(newHeights[i] < newHeights[stack.peek()]){
                    int middle = stack.pop();
                    int w = i - stack.peek() - 1;
                    int h =  newHeights[middle];
                    res = Math.max(res, w * h);
                }
                stack.push(i);
        }
        return res;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值