leetcode : Largest Rectangle in Histogram
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 height = [2,1,5,6,2,3],
return 10.
首先想到的是暴力求解,即对于每一个index = i,分别向左 右两边搜索第一个比它小的值的index,然后求宽度,计算面积。
意料之中的超时了
代码:
class Solution { public: int largestRectangleArea(vector<int> &height) { int ret = INT_MIN; for(int i = 0; i < height.size(); ++i){ ret = max(ret, getMax(height, i)); } return ret; } int getMax(vector<int> &height, int pos){ int count = 1; int left = pos - 1,right = pos + 1; while(left >= 0 && height[pos] <= height[left--]) ++count; while(right < height.size() && height[pos] <= height[right++]) ++count; return count * height[pos]; } };
开始优化,可以发现,如果height[i]< height[i+1] 那么右边界取i+1面积总会比取i要大。于是可以一直向右遍历,直到遇见height[i]> height[i+1] 这个时候以height[i]为右边界,然后再找左边界。这个方法可以AC,但是还可以做的更好。
// O(n^2) with pruning public int largestRectangleArea1(int[] height) { // Start typing your Java solution below // DO NOT write main() function int area = 0; for (int i = 0; i < height.length; i++) { for (int k = i + 1; k < height.length; k++) { if (height[k] < height[k - 1]) { i = k - 1; break; } else { i = k; } } int lowest = height[i]; for (int j = i; j >= 0; j--) { if (height[j] < lowest) { lowest = height[j]; } int currArea = (i - j + 1) * lowest; if (currArea > area) { area = currArea; } } } return area; }
在上面的方法,求左边界的时候,每次左边界左移一次,都需要进行一次比较,求一次lowest,那么我们可以只存储height[i]值最小的那个i;
可以维护这样一个栈,栈里存储着递增但不连续的index,同时height[index]是递增的,那么当height[i]小于height[top]的时候,就分别以top,top-1,top-2为最小值,计算最大面积。同时将这些height大于height[i]的节点弹出,同时将i入栈
如果height[i]大于height[top]的话,直接将i进栈。
这样可以保证栈里的所有index 恰好对应了第二个方法中的所有lowest的节点的index。大量减少了比较次数
最终代码:
class Solution { public: int largestRectangleArea(vector<int> &height) { stack<int> s; int i = 0; int maxArea = 0; height.push_back(0); while(i < height.size()){ if(s.empty() || height[i] > height[s.top()]) s.push(i++); else{ int right = s.top(); s.pop(); maxArea = max(maxArea, height[right] * (s.empty() ? i : i - s.top() - 1)); } } return maxArea; } };
注意if语句的判断条件,height[i]> height[s.top()]而不是 >=,这样可以保证height值相同的节点,栈里也只有一个,如果这些连续相等节点之后还有大量节点的话,会很明显的影响算法效率。使用>是76ms过,用>=是104ms过。
浙公网安备 33010602011771号