1. 程式人生 > >leetcode 84. Largest Rectangle in Histogram

leetcode 84. Largest Rectangle in Histogram

分享 說明 -i right -h set code tco his

link

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.

For example,
Given heights = [2,1,5,6,2,3],
return 10.

題意:

給出條形圖,求出其中面積 ,看圖片題意很明確。

思路:

只能想出來O(N^2)的方法。但是感覺可以優化到O(N),因為有 很多重復步驟。

於是搜了一下題解。

簡單的來說,我想對於某一個位置i,看以heights[i]為高的矩陣最遠可以向左右延伸到哪裏。

在這個子問題上,O(N)的做法自然是往左右掃。但這沒有用到上一個位置的信息,簡單的說,如果上一個位置比它高,那它能到的地方一定不會比上一個位置近。更玄學一點的,也沒有用到前面高度的信息。

為此,做法是維護一個棧。並保證棧內元素單調遞增。

保證棧內元素單調遞增的方法是,每次放進元素前,將大於它的元素退棧。然後再將它放進去。

這樣做的原因是,退完的棧頂一定是< 這個高度的最近的地方。

那麽能延伸到的邊界就是棧頂了。

如果棧為空的話,說明沒有一個值比它小,就可以延伸到這個條形圖的邊界。

遍歷所有元素需要O(N),由於每個元素只入棧一次,因此復雜度還是O(N)

這樣從左往右做一遍,從右往左做一遍,則可以獲得一個點到左右的最遠距離。然後有了長寬就可以計算了。

code

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        
if(heights.size() == 0) return 0; stack<int> s; int ans = 0; vector<int> leftPos(heights.size()); for(int i = 0; i < heights.size(); i++){ while(!s.empty() && heights[s.top()] >= heights[i]) s.pop(); if(s.empty()) leftPos[i] = 0; // no one is lower than i else leftPos[i] = s.top() + 1; // s.top is first one lower than i, s.push(i); } while(!s.empty()) s.pop(); for(int i = heights.size() - 1; i >= 0; i--){ while(!s.empty() && heights[s.top()] >= heights[i]) s.pop(); int rightPos = heights.size() - 1; if(!s.empty()) rightPos = s.top() - 1; int tmp = heights[i] * (rightPos - leftPos[i] + 1); ans = max(tmp, ans); s.push(i); } return ans; } };

leetcode 84. Largest Rectangle in Histogram