42. 接雨水 - 力扣(LeetCode)
暴力解法:就是遍历数组,找左右两侧最高的柱子,然后用两者之间的小值减去当前柱子的高度就得到的当前柱子上的雨水,如果大于0则加入结果中。也就是按列来求解
单调栈
需要掌握的重点方法,底层思想就是按行来计算雨水,维护一个栈存放柱子下标,遍历柱子,有三种情况
- 比栈头低:这种情况直接入栈就行,因为这一行不产生雨水
- 跟栈头一样高:栈头出栈,然后将当前下标加入。这么做的理由是需要保证从大到小排布,这样出栈之后的新栈头就是左侧柱了(当前遍历柱为右侧柱)
- 比栈头高:这种情况下就会生成雨水,体积 =( min(右侧柱子高度,左侧柱子高度)-中间柱子高度)*宽度。实际操作就是栈头出栈,找到栈头高度,然后比较当前遍历柱子和新栈头柱子高度取小值,然后两者相减得到柱高度,再通过左柱下标和右柱下标找到宽度,一乘就是高度了。这里要一直循环直到柱子栈头柱子高度高于当前遍历柱子高度或者空栈后把当前柱子如栈。
这里把画面想象为每计算完一次雨水就把那一行填平就能理解算法流程了
84. 柱状图中最大的矩形 - 力扣(LeetCode)
只能想到一个暴力解,提交的时候超时了
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
int res = 0;
for(int i=0;i<heights.size();i++){
int height = heights[i];
int temp = height;
for(int low = i-1;low>=0;low--){
if (heights[low]>=height){
temp += height;
}else break;
}
for(int fast = i+1;fast<heights.size();fast++){
if (heights[fast]>=height){
temp += height;
}else break;
}
res = max(res,temp);
}
return res;
}
};
看了一下思路,就反应过来了,和接雨水一个思路
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
stack<int> st;
int result = 0;
heights.insert(heights.begin(),0);
heights.push_back(0);
st.push(0);
for(int i=1;i<heights.size();i++){
int height = heights[i];
if(height>heights[st.top()]){
st.push(i);
}else if(height == heights[st.top()]){
st.pop();
st.push(i);
}else{
while(!st.empty() && heights[st.top()]>height){
int mid = st.top();
st.pop();
if (!st.empty()) {
int left = st.top();
int right = i;
int w = right - left - 1;
int h = heights[mid];
result = max(result, w * h);
}
}
st.push(i);
}
}
return result;
}
};