Trapping Rain Water
Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining.
Example:
Input: [0,1,0,2,1,0,1,3,2,1,2,1]
Output: 6
解析
给出一个数组,计算出储水量,如上图所示。
解法1:暴力
对每一个点,往左搜索出左边的最大高度,往右搜索出右边的最大高度,得到当前点的储水量为二者高度较小着减去当前高度。
class Solution {
public:
int trap(vector<int>& height) {
int size = height.size();
int ans = 0;
for(int i=1;i<size;i++){
int maxleft = 0, maxright = 0;
for(int j=i;j>=0;j--)
maxleft = max(maxleft, height[j]);
for(int j=i;j<size;j++)
maxright = max(maxright, height[j]);
ans += min(maxleft, maxright) - height[i];
}
return ans;
}
};
解法2:动态规划
根据解法1的思想,一开始我是想用两个数组,分别表示当前点的左边最大高度和右边最大高度,这样的话需要三次遍历和两倍空间。
后面看了大神解法,只需要开一个数组就行了,先从左往右扫,获得左边的的最大高度,然后从右往左扫,获取右边的最大高度,然后与当前数组中最大的左边高度相比,取较小值,如果较小值大于当前高度,则加上当前储水量。
class Solution {
public:
int trap(vector<int>& height) {
int size = height.size();
int ans = 0;
int tmp = 0;
vector<int> dp(size, 0);
for(int i=0;i<size;i++){
dp[i] = tmp;
tmp = max(height[i], tmp);
}
tmp = 0;
for(int i=size-1;i>=0;i--){
dp[i] = min(tmp, dp[i]);
tmp = max(tmp, height[i]);
if(dp[i] > height[i])
ans += dp[i]-height[i];
}
return ans;
}
};
解法3:双指针
同样是借助解法1的思想,使用left和right两个指针,并且设置maxleft和maxright两个值分别表示左边最大值和右边最大值。
- 初始化left=0,right=size-1, maxleft = maxright = 0;
- 当left<right时:
如果height[left]<=height[right]: 更新maxleft = max(maxleft,height[left]), 判断是否要加入差值,left++。
否则,同理,right–。
class Solution {
public:
int trap(vector<int>& height) {
int size = height.size();
int ans = 0;
int maxleft = 0;
int maxright = 0;
int left =0, right = size-1;
while(left < right){
if(height[left] <= height[right]){
maxleft = max(maxleft, height[left]);
if(maxleft > height[left])
ans += maxleft- height[left];
left ++;
}
else{
maxright = max(maxright, height[right]);
if(maxright > height[right])
ans += maxright - height[right];
right --;
}
}
return ans;
}
};
解法4:栈stack
利用单调栈,维持一个单调递减栈,栈中保存的元素是下标,保证下标对应的高度呈单调递减。
当栈不为空,当前高度大于栈顶时,先判断栈的大小是否大于2,如果小于2则直接break,否则计算距离和边界高度,得到储水量。
当前高度小于或者等于栈顶时,直接压栈。
class Solution {
public:
int trap(vector<int>& height) {
int size = height.size();
int i=0, ans=0;
stack<int> st;
while(i < size){
while(!st.empty() && height[i] > height[st.top()]){
int top = st.top();
st.pop();
if(st.empty())
break;
int distance = i - st.top() -1;
int bound = min(height[i], height[st.top()]) - height[top];
ans += distance*bound;
}
st.push(i);
i++;
}
return ans;
}
};
参考
https://leetcode.com/problems/trapping-rain-water/submissions/
http://www.cnblogs.com/grandyang/p/4402392.html