leetcode_50 Trapping Rain Water

161 篇文章 0 订阅

题目:存储雨水

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

方法一:暴力破解法

Intuition

Do as directed in question. For each element in the array, we find the maximum level of water it can trap after the rain, which is equal to the minimum of maximum height of bars on both the sides minus its own height.

Algorithm

  • Initialize ans=0ans=0
  • Iterate the array from left to right:
    • Initialize left_max=0 and right_max=0
    • Iterate from the current element to the beginning of array updating:
      • left_max=max(left_max,height[j])
    • Iterate from the current element to the end of array updating:
      • right_max=max(right_max,height[j])

Add min(left_max,right_max)−height[i] to ans

  • Time complexity: O(n^2) For each element of array, we iterate the left and right parts.

  • Space complexity: O(1) extra space.

每次求得 位置 i 的蓄水量,left,right为左右遮挡物

class Solution {
public:
    int trap(vector<int>& height) {
        int n  = height.size();
        if(n == 0)
            return 0;
        int res = 0;
        for(int i = 0; i < n; i++)
        {
            int lm = 0, rm = 0;
            
            for(int j = 0; j < i; j++)
            {
                lm = max(lm,height[j]);
            }
            for(int j = i + 1; j < n; j++)
            {
                rm = max(rm,height[j]);
            }
            
            int swater = min(lm,rm) - height[i];
            
            if(swater > 0)
                res += swater;
        }
        return res;
    }
};

方法二:动态规划

 

Algorithm

  • Find maximum height of bar from the left end upto an index i in the array left_max.
  • Find maximum height of bar from the right end upto an index i in the array right_max.
  • Iterate over the height array and update ans:
    • Add min(left_max[i],right_max[i])−height[i] to ans
class Solution {
public:
    int trap(vector<int>& height) {
        int n = height.size();
        if(n == 0)  return 0;
        int ans = 0;
        vector<int> lm(n),rm(n);
        lm[0] = height[0];
        for(int i = 1; i < n; i++)
        {
            lm[i] = max(lm[i - 1],height[i]);
        }
        
        rm[n-1] = height[n - 1];
        for(int i = n - 2; i >= 0; i--)
        {
            rm[i] = max(rm[i + 1],height[i]);
        }
        
        for(int j = 1; j < n; j++)
        {
            ans += min(lm[j],rm[j]) - height[j];
        }
        return ans;
    }
};

方法三:使用栈

  • Use stack to store the indices of the bars.
  • Iterate the array:
    • While stack is not empty and height[current]>height[st.top()]
      • It means that the stack element can be popped. Pop the top element as top.
      • Find the distance between the current element and the element at top of stack, which is to be filled. distance=current−st.top()−1
      • Find the bounded_height=min(height[current],height[st.top()])−height[top]
      • Add resulting trapped water to answer ans+=distance×bounded_height
    • Push current index to top of the stack
    • Move current to the next position
class Solution {
public:
    int trap(vector<int>& height) {
        int n = height.size();
        int ans = 0,cur = 0;
        stack<int> stk;
        while(cur < n)
        {
            while(!stk.empty() && height[cur] > height[stk.top()])
            {
                int top = stk.top();
                stk.pop();
                if(stk.empty())
                    break;
                int distance = cur - stk.top() - 1;
                int bound = min(height[cur],height[stk.top()]) - height[top];
                
                ans += distance * bound;
            }
            stk.push(cur);
            cur++;
        }
        return ans;    
    }
};

方法四: 双指针

  • Initialize left pointer to 0 and right pointer to size-1
  • While left<right, do:
    • If height[left] is smaller than height[right]
      • If height[left]≥left_max, update left_max
      • Else add left_max−height[left] to ans
      • Add 1 to left.
    • Else
      • If height[right]≥right_max, update right_max
      • Else add right_max−height[right] to ans
      • Subtract 1 from right
class Solution {
public:
    int trap(vector<int>& height) {
        int left = 0, right = height.size() - 1;
        int ans = 0;
        int lm = 0, rm = 0;
        while(left < right)
        {
            if(height[left] < height[right])
            {
                if(height[left] >= lm)
                {
                    lm = height[left];    
                }
                else
                {
                    ans += lm - height[left];
                }
                ++left;
            }
            else
            {
                if(height[right] >= rm)
                {
                    rm = height[right];
                }
                else
                {
                    ans += rm - height[right];
                }
                --right;
            }
        }
        return ans;
    }
};

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值