42. 接雨水

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

示例 1:

42. 接雨水_第1张图片

输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 

示例 2:

输入:height = [4,2,0,3,2,5]
输出:9

提示:

  • n == height.length
  • 1 <= n <= 2 * 104
  • 0 <= height[i] <= 105

双指针

class Solution {
public:
    int trap(vector& h) {
        //有凹槽,才会接水。

        //双指针。
        int rmax = 0,lmax =0;
        int i = 0,j = h.size()-1;
        int sum = 0;
        while(i < j){
            lmax = max(lmax,h[i]); // 每次比较是 比较左边的
            rmax = max(rmax,h[j]); // 每次判断的是右边的
            if(lmax < rmax){ // 目标值的左边最大值 小于 右边最大值。装水取决于短板
                sum += lmax - h[i];
                i++;
            }
            else{
                sum += rmax - h[j];
                j--;
            }
        }
        return sum;
    }
};

单调栈

class Solution {
public:
    int trap(vector& h) {
        //单调栈。找到目标值的左边第一个比自己大的,和 右边第一个比自己大的
        //取两个大的 较小者才决定装多少水
        int sum = 0;
        stackst;
        st.push(0);
        for(int i = 1;i < h.size();i++){
            if(h[i] < h[st.top()]) st.push(i);
            else if(h[i] == h[st.top()]) st.push(i);
            else {
                while(!st.empty() && h[i] > h[st.top()]){
                    int mid = h[st.top()];//目标值
                    st.pop();
                    if(!st.empty()){
                        int right = h[i];
                        int left = h[st.top()];
                        int hh = min(right, left) - mid;
                        int w = i-st.top()-1;
                        sum += hh*w;
                    }    
                }
                st.push(i);
            }
        }
        return sum;
    }
};

你可能感兴趣的:(leetcode练习,c++,动态规划,算法)