naive的解法,O(n^2),应该谁都能想到
枚举中间,再枚举左右边界。
O(n) ,网上有个单调stack的解法,不过没看懂。。。空了再研究下
我们还是从naive的解法入手吧
那个做了好多好多的无用运算
比如我算了i=2的leftmost的时候,算i=3的时候也会重复计算
那么,我们把运算记录下来嘛。
left[i]表示i左边连续大于等于height[i]的边界
初始化left[i] = i
if height[i] <= height[left[i]-1] then left[i] = left[left[i]-1]
left[i]-1,表示i的leftmost的前面那个,如果他的高度>=i的高度,那么当然就是更新leftmost了
既然这样那么left[left[i]-1]就是i的leftmost啦
如此迭代下去(感觉有点像并查集
rightmost同理
class Solution { public: void foundLeft(vector<int>&most , vector<int>&height) { int size = height.size(); for(int i = 1 ; i < size ; i++) { if(height[i] > height[most[i-1]]) { } else { while(most[i] && height[i] <= height[most[i]-1]) most[i] = most[most[i]-1]; } } } void foundRight(vector<int>&most , vector<int>&height) { int size = height.size(); for(int i = size - 2 ; i >= 0 ; i --) { if(height[i] > height[most[i+1]]) { } else { while(most[i] < size-1 && height[i] <= height[most[i]+1]) most[i] = most[most[i]+1]; } } } int largestRectangleArea(vector<int> &height) { int size = height.size(); if(size == 1) return height[0]; if(size <= 0) return 0; vector<int> left(size); vector<int> right(size); for(int i = 0 ; i < size ; i++) { left[i] = i; right[i] = i; } foundLeft(left , height); foundRight(right , height); int result = 0; for(int i = 0 ; i < size ; i++) { result = max(result , (right[i] - left[i] + 1)*height[i]); } return result; } };
----------
单调stack
class Solution { public: int largestRectangleArea(vector<int> &height) { stack<int> st; height.push_back(0); int ans = 0; for (int i = 0; i < height.size();) { if (st.empty() || height[i] > height[st.top()]) { st.push(i++); } else { int p = st.top(); st.pop(); if (st.empty()) { ans = max(height[p] * i, ans); } else { ans = max(height[p] * (i - st.top()-1), ans); } } } return ans; } };