leetcode84

Given n non-negative integers representing the histogram's bar height where the width of each bar is 1, find the area of largest rectangle in the histogram.
Example:
Input: [2,1,5,6,2,3]
Output: 10
 
 
Stack 递增栈。
想法:遍历的时候,把当前条条和以前的(stack.peek)对比。
当你看到条条比peek高,你知道当前这根条条有希望合并到之后一些条条的答案里(因为后面可能还是递增的),你就先偷懒。只是压入栈,不处理。
当你看到条条比peek矮,比如看到了heights[4] = 2 < 6你不能偷懒了要开始对stack里之前的东西进行一些计算了。计算方法就是在peek比当前条条还高着的情况下,不断pop以前的条条,通过高宽计算面积去打擂台。算完才把这个小矮条压入栈给以后用。
1)高就是当前pop出来的这条的高度,比如5.
2)宽就是被夹在中间的那一段,左边是现在的peek(不被算在内 peek: 如1),右边是遍历过程中的新矮条位置(i: 如4) 这两个左右定位符都不被包括在内,例如此时算出来的宽度是4-1-1。另外解释一下,我们选择这个固定下来anchor住的右边的原因是,我们知道stack里一直递增状态,当我们pop到当前这个位置的时候,我知道之前被pop出来的那些肯定也有当前这条那么高,所以我肯定可以一直延伸到新矮条前面的。
 
细节:
1.如果遍历完一次后,stack里还剩下东西,还要继续用类似方法处理,这次就是把右边定位在最后一根条条的右边。这个计算可以通过小trick合并到前面的遍历内。
2.如果pop后要算长宽时,发现stack空了,那宽度就是让左边看成index-1了,也就是左边的条条全都包括进来按当前height计算。因为你能把递增栈stack掏空说明你现在pop出来的这条,是你见过有史以来最矮的一条,那么所有前面的都可以贡献了。
 
这题好难,多跑test多体会多回顾code。
 
实现1:代码有冗余,但思路直接一些
class Solution {
    public int largestRectangleArea(int[] heights) {
        int ans = 0;
        Stack<Integer> stack = new Stack<>();
        
        for (int i = 0; i < heights.length; i++) {
            if (stack.isEmpty() || heights[i] >= heights[stack.peek()]) {
                stack.push(i);
            } else {
                while (!stack.isEmpty() && heights[i] < heights[stack.peek()]) {
                    int height = heights[stack.pop()];
                    int width = stack.isEmpty() ? i : i - 1 - stack.peek();
                    ans = Math.max(ans, height * width);
                }
                stack.push(i);
            }
        }
        
        // for the case after all the iteration, there's still elements left in the stack.
        while (!stack.isEmpty()) {
            int height = heights[stack.pop()];
            int width = stack.isEmpty() ? heights.length : heights.length - 1 - stack.peek();
            ans = Math.max(ans, height * width);
        }
        return ans;
    }
}

实现2:九章,去除冗余,有一些小trick。

public class Solution {
    public int largestRectangleArea(int[] height) {
        if (height == null || height.length == 0) {
            return 0;
        }
        
        Stack<Integer> stack = new Stack<Integer>();
        int max = 0;
        for (int i = 0; i <= height.length; i++) {
            int curt = (i == height.length) ? -1 : height[i];
            while (!stack.isEmpty() && curt <= height[stack.peek()]) {
                int h = height[stack.pop()];
                int w = stack.isEmpty() ? i : i - stack.peek() - 1;
                max = Math.max(max, h * w);
            }
            stack.push(i);
        }
        
        return max;
    }
}
 
原文地址:https://www.cnblogs.com/jasminemzy/p/9764297.html