带你手撕单调栈(二)
描述
给定一个整形数组arr,已知其中所有的值都是非负的,将这个数组看作一个柱子高度图,计算按此排列的柱子,下雨之后能接多少雨水。

示例1
输入:
[3,1,2,5,2,4]
复制
返回值:
5
复制
说明:
数组 [3,1,2,5,2,4] 表示柱子高度图,在这种情况下,可以接 5个单位的雨水,蓝色的为雨水
示例2
输入:
[4,5,1,3,2]
返回值:
2
class Solution {
public:
/**
* max water
* @param arr int整型vector the array
* @return long长整型
*/
long long maxWater(vector<int>& arr) {
// write code here
/**
拿到题目先分析
这个东西,要知道某个地点能蓄水多少就要知道左边比自己高的第一个高度是多少,右边的比自己高的第一个高度是多少
那么怎么求右边比自己高度是多少
又发现是一个先进后出的结构,正好要计算左右,那么我们就一正一反的来
**/
// 先求右边,这是正向的,处理在while里面
stack<int> st;
vector<int> right_high(arr.size(),-1);
for(int i=0;i<arr.size();i++) {
while(!st.empty() && arr[st.top()]<=arr[i]) {
right_high[st.top()] = i;
st.pop(); // 正的不能直接pop后不管
}
st.push(i);
}
// 清空st
while(!st.empty()) {
st.pop();
}
// 开始倒序,加入哨兵节点
arr.insert(arr.begin(), 0);
vector<int> left_hight(arr.size());
for(int i=0;i<arr.size();i++) {
while(!st.empty() && arr[st.top()]<=arr[i]) {
st.pop();
}
left_hight[i]=st.empty()?-1:st.top()-1; // 这是反向的处理在while外面
st.push(i);
}
left_hight.erase(left_hight.begin());
arr.erase(arr.begin());
// for(auto value : left_hight) {
// cout<<value<<" ";
// }
// cout<<endl;
// for(auto value : right_high) {
// cout<<value<<" ";
// }
// cout<<endl;
long long res = 0;
for(int i=0;i<left_hight.size();i++) {
if(left_hight[i]>=0 && right_high[i]>=0) {
res+=(min(arr[left_hight[i]],arr[right_high[i]])-arr[i])*(long long)(right_high[i]-left_hight[i]-1);
}
}
return res;
}
};

4万+

被折叠的 条评论
为什么被折叠?



