题目:
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.
题解:
做编程题一定要自己AC了再去看discussion,之前一直草草的刷题,感觉忘得好快,尤其是边界条件的处理上一点长进也没有,这次hard题做了半个多小时,从开始看题到提交(提交了3次,都是小错误。。。太不细心了,这更加说明了白板编程的重要性,不要用IDE),完全自己码出来,以后会坚持这样做,否则去面试什么的肯定跪,也不利于思维逻辑能力的提高。
Solution 1 ()
class Solution { public: int largestRectangleArea(vector<int> height) { if (height.empty()) return 0; stack<int> high; int maxArea = 0; high.push(0); height.push_back(0); for (int i = 1; i < height.size(); ++i) { while (!high.empty() && height[i] < height[high.top()]) { int index = high.top(); high.pop(); if (high.empty()) { maxArea = max((i - 0) * height[index], maxArea); } else { maxArea = max((i - high.top() - 1) * height[index], maxArea); } } high.push(i); } return maxArea; } };
Solution 2 ()
class Solution { public: int largestRectangleArea(vector<int> &height) { int ret = 0; height.push_back(0); vector<int> index; for(int i = 0; i < height.size(); i++) { while(index.size() > 0 && height[index.back()] >= height[i]) { int h = height[index.back()]; index.pop_back(); int sidx = index.size() > 0 ? index.back() : -1; if(h * (i-sidx-1) > ret) ret = h * (i-sidx-1); } index.push_back(i); } return ret; } };
Diveide and Conquer 思想比较容易懂, 就是写起来的时候边界条件有点麻烦。
Solution 3 ()
class Solution { int maxCombineArea(const vector<int> &height, int s, int m, int e) { // Expand from the middle to find the max area containing height[m] and height[m+1] int i = m, j = m+1; int area = 0, h = min(height[i], height[j]); while(i >= s && j <= e) { h = min(h, min(height[i], height[j])); area = max(area, (j-i+1) * h); if (i == s) { ++j; } else if (j == e) { --i; } else { // if both sides have not reached the boundary, // compare the outer bars and expand towards the bigger side if (height[i-1] > height[j+1]) { --i; } else { ++j; } } } return area; } int maxArea(const vector<int> &height, int s, int e) { // if the range only contains one bar, return its height as area if (s == e) { return height[s]; } // otherwise, divide & conquer, the max area must be among the following 3 values int m = s + (e-s)/2; // 1 - max area from left half int area = maxArea(height, s, m); // 2 - max area from right half area = max(area, maxArea(height, m+1, e)); // 3 - max area across the middle area = max(area, maxCombineArea(height, s, m, e)); return area; } public: int largestRectangleArea(vector<int> &height) { if (height.empty()) { return 0; } return maxArea(height, 0, height.size()-1); } };
为什么下面的代码过不了???
class Solution { public: int largestRectangleArea(vector<int> &height) { if (height.empty()) return 0; return maxArea(height, 0, height.size() - 1); } int maxArea(vector<int> height, int begin, int end) { if (begin == end) { return height[begin]; } int mid = begin + (end - begin) / 2; int mArea = maxArea(height, begin, mid); mArea = max(mArea, maxArea(height, mid + 1, end)); mArea = max(mArea, maxCombineArea(height, begin, mid, end)); return mArea; } int maxCombineArea(vector<int> height, int begin, int mid, int end) { int maxArea = 0; int left = mid, right = mid + 1; int high = min(height[left], height[right]); while (left >= begin && right <= end) { high = min(high, min(height[left], height[right])); maxArea = max(maxArea, (right - left + 1) * high); if (left == begin) { ++right; } else if (right == end) { --left; } else { if (height[left - 1] > height[right + 1]) { --left; } else { ++right; } } } return maxArea; } };