leetcode84 - Largest Rectangle in Histogram - hard

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.

 


Above is a histogram where width of each bar is 1, given height = [2,1,5,6,2,3].

 


The largest rectangle is shown in the shaded area, which has area = 10 unit.

 

Example:

Input: [2,1,5,6,2,3]
Output: 10
 
维护一个递增栈, 因为我们要考虑宽度的,栈里存index。遍历所有的bar尝试push,如果当前bar的高度比栈顶要小了,依次把栈里比它大的的pop出来,再把它push进去。pop的这个过程就是计算面积打擂台的时候:pop出来的高度肯定是逐渐变小的,所以高就取pop出来的这个,宽要注意,如果栈都pop空了,说明当前这个高度是最小的,就相当于木桶原理那个最短板,它之前的所有bar都能提供宽度。其他情况下,宽取的是夹在中间的那段,左是当前的栈顶,右是当前遍历到的短板,左右都不包含。
 
单调栈的问题难都难在思路,不在代码,有很多细节要注意,想清楚以后实现很容易。
细节:
1. 为了最后一个bar也能被考虑到,先往heights里填个0
2. 每个bar要么直接被push进栈了,要么操作后也要被push进去,且只会进栈一次,pop出来了就是没用了,不会再放回去的
3. pop出来的前提是它比当前遍历到的那个大!
4. 宽度计算,左边要考虑现在的栈顶的idx,而不是刚被pop出来的这个的idx,他们不一定是相邻的关系!(i-cur_idx != i-1-st.top()!!!!!)
比如[4,2,0,3,2,5] 这个例子,0这个高度是pop不出来的,所以遍历到结尾然后逐一pop到idx=4的时候,栈顶是idx=2!也就是说2-4直接的之前pop出去过了,但它们是比idx=4的这个要高的,要算进去。
 
实现:
class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        
        int res = 0;
        
        stack<int> st;
        heights.push_back(0);
        for(int i=0; i){
            if(st.empty() || (!st.empty() && heights[i] >= heights[st.top()])) 
                st.push(i);    
            else{
                while(!st.empty() && heights[st.top()] > heights[i]){
                    int idx = st.top(); 
                    st.pop();
                    int h = heights[idx];
                    int w = st.empty() ? i : (i-1-st.top());
                    res = max(res, h * w);  
                }
                st.push(i); 
            }
        }
        
        return res;
        
    }
};

 

你可能感兴趣的:(leetcode84 - Largest Rectangle in Histogram - hard)