LeetCode 84. Largest Rectangle in Histogram

ver0:

用递归,首先判断整个高度是否单调递增,如果是的话,从第一个高度开始,假设该高度是最终最大矩形的高度,得到面积,一直遍历到最后一个高度,这样就得出了最大面积;如果不是单调递增,则先得到最小高度的位置,根据递归得到最小高度左边的最大矩形面积,再得到最小高度右边的最大矩形面积,又得到以最小高度为最终高度、整体宽度为最终宽度的面积,在这三者中取最大值,即为结果。

16ms

 1 class Solution {
 2 public:
 3     int largestRectangleArea(vector<int>& heights) {
 4         if(heights.size() == 0) return 0;
 5         return getRes(heights, 0, heights.size());
 6     }
 7     int getRes(vector<int>& height, int s, int e){//s:start e:end [start,end)
 8         if(s + 1 >= e) return height[s];
 9         int sorted = true;
10         int minH = s;
11         for(int i = s + 1; i < e; ++i){
12             if(height[i] < height[i-1]) sorted = false;
13             if(height[i] < height[minH]) minH = i;
14         }
15         if(sorted){
16             int res = 0;
17             for(int i = s; i < e; ++i){
18                 res = max(res, height[i] * (e - i));
19             }
20             return res;
21         }
22         
23         int left = (minH == s) ? 0 : getRes(height, s, minH);
24         int right = (minH == e - 1) ? 0 : getRes(height, minH + 1, e);
25         int res = max(max(left, right), height[minH] * (e - s));
26         return res;
27         
28     }
29 };

 

ver1:

16ms

另外一种比较易懂的算法。最终最大矩形必定至少包括一个高度条,因此以每个高度条为对象,只要算出包含该高度条的最大矩形,再从这些结果中取最大值,就可以得出整体的最大矩形。那么包含该高度条的最大矩形满足什么条件呢,首先因为最大矩形必定包含该高度条,因此不能出现比该高度条矮的高度条,也就是说,从该高度条向左,最大矩形截止到比该高度条矮的地方(或一直到总体高度的开头),这个比该高度条矮的高度条位置为l,从该高度条向右,最大矩形截止到比该高度条矮的地方(或一直到总体高度的结尾),这个比该高度条的高度条位置为r。综上,这个最大矩形高度为该高度条的高度,宽度为r-l-1(因为l和r都不包括进最大矩形)。

那么如何计算l和r呢,首先说说思路简单但是耗时多的算法。计算l,对于每个高度条heights[i],如果height[i]>height[i-1],那么l=i-1;否则的话,就从i开始一直减到0,找到比height[i]小的高度条。计算r,类似思路。

 1 for (int i = 1; i < height.length; i++) {
 2           if (height[i] > height[i - 1]) {
 3               lessFromLeft[i] = i - 1;
 4           }
 5           else  {
 6               int p = i - 1;
 7               while (p >= 0 && height[p] >= height[i]) {
 8                   p--;
 9               }
10               lessFromLeft[i] = p;
11           }
12      }

为了改进这个算法,要用上类似动态规划的思想。计算l,对于每个高度条heights[i],如果height[i]>height[i-1],那么l=i-1;否则的话,因为height[p]>=height[i],而height[p]的l必定大于等于height[i]的l,所以此时p可以直接跳到height[p]的l,就不必一个一个比较过去了,而是直接赋值了。

1 while (p >= 0 && height[p] >= height[i]) {
2       p = lessFromLeft[p];
3 }

注意lessLeft[0]和lessRight[len-1]的初始化,考虑第一个和第二个高度为n、n-1的情况,此时对于第一个高度条,r = 1, r - l - 1 = 1,因此l为-1;倒数第二个和最后一个的高度为n-1、n,最后一个高度条l = len - 2, r - l - 1 = 1,因此r = len。

 1 class Solution {
 2 public:
 3     int largestRectangleArea(vector<int>& heights) {
 4         if(heights.size() == 0) return 0;
 5         int len = heights.size();
 6         int* lessLeft = new int[len];
 7         lessLeft[0] = -1;
 8         int* lessRight = new int[len];
 9         lessRight[len - 1] = len;
10         
11         for(int i = 1; i < len; ++i){
12             if(heights[i - 1] < heights[i])
13                 lessLeft[i] = i - 1;
14             else{
15                 int p = i - 1;
16                 while(p >= 0 && heights[p] >= heights[i])
17                     p = lessLeft[p];
18                 lessLeft[i] = p;
19             }
20         }
21         
22         for(int i = len - 2; i >= 0; --i){
23             if(heights[i + 1] < heights[i])
24                 lessRight[i] = i + 1;
25             else{
26                 int p = i + 1;
27                 while(p < len && heights[p] >= heights[i])
28                     p = lessRight[p];
29                 lessRight[i] = p;
30             }
31         }
32         
33         int area = 0;
34         for(int i = 0; i < len; ++i){
35             area = max(area, heights[i] * (lessRight[i] - lessLeft[i] - 1));
36         }
37         return area;
38         
39         
40     }
41     
42 };

 

 

还有stack的算法,看不懂,留坑。

https://leetcode.com/discuss/90454/5ms-o-n-java-solution-explained-beats-96%25

posted @ 2016-04-05 21:15  co0oder  阅读(297)  评论(0编辑  收藏  举报