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;
}
};
by 1957
浙公网安备 33010602011771号