[LeetCode] 42. Trapping Rain Water

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值