随想录训练营Day60 | DP - - 84.柱状图中最大的矩形

75 阅读1分钟

随想录训练营Day60 | DP - - 84.柱状图中最大的矩形

标签: LeetCode闯关记


84.柱状图中最大的矩形

思路 对于stack.peek()来说,找到右边第一个比自己小的元素, 并找到左边第一个比自己小的元素————即通过3个元素确定矩形的宽度(高度为heights[stack.peek()])。

  • 右边第一个比自己小的元素: 借助单调栈, 当heights[i] < heights[stack.peek()],即找到右边第一个比自己小的元素heights[i]
  • 左边第一个比自己小的元素: 在单调栈中stack.peek()的下一个元素(单调栈递减,下一个元素下标所对应的元素一定比 heights[stack.peek()] 小;
  • 对于无法找到3个元素以确定矩形面积,通过在原数组首尾加上0巧妙解决!!!太妙了
class Solution {
    public int largestRectangleArea(int[] heights) {
        int areaMax = 0;
        Stack<Integer> stack = new Stack<>();
        int [] newHeights = new int[heights.length + 2];//在原数组首尾加上0,以巧妙地解决找不到三个元素地情况,即1.左边有矮右边无;2.右边无矮左边有;3.左右两边都没有矮;
        newHeights[0] = 0;
        newHeights[newHeights.length - 1] = 0;
        for (int index = 0; index < heights.length; index++){
            newHeights[index + 1] = heights[index];
        }

        heights = newHeights;//注意引用传递(Reference Passing)
        stack.push(0);

        for (int i = 1; i < heights.length; i++) {
            while (!stack.isEmpty() && heights[i] < heights[stack.peek()]){
                int target = stack.pop();//写了死循环int target = stack.peek(); 一直没有pop();
                int right = i;
                if(!stack.isEmpty()){
                    int left = stack.peek();
                    int width = right - left - 1;
                    int height = heights[target];
                    if(areaMax < width*height){
                        areaMax = width * height;
                    }
                }
            }
            stack.push(i);
        }
        return areaMax;
    }
}

过程中所犯错误: 显示超时Time Limit Exceeded
因为写了死循环,详见代码注释