单调栈: 接雨水

 解法: 雨水面积 = 底边长w*雨水高度h

双指针:

  • 求每个位置的水位高度,以当前位置为中心,双指针分别向左右寻找最高边界。
  • h = min(lHeight, rHeight) - height[i]; w=1

动态规划:

  • 根据已知的边界高度和当前高度比较,确定当前位置的左右边界高度,取最高的左右高度值
  • int[len+2][2]: 存放个位置的左边界高,右边界高;首尾设置虚拟节点表示边界,高度为0
  • 遍历高度:左到右确定左界值。右到左确定右界值
  • h = min(lHeight, rHeight) - height[i]; w=1

单调栈:

  • 栈内元素对应高度值:大到小(栈底到栈头),即栈内可确定左边界(栈内存放下标)
  • 新加元素 符合 单调性:直接加入
  • 新加元素 = 栈头旧元素: 旧元素出栈,新元素入栈 (保证左侧的最右边边界)
  • 新加元素 > 栈头旧元素:右边界确定,栈头出栈,当前栈头为左边界,计算当前凹槽高度的存水量,重复该步骤,直到满足新元素入栈条件
  • 宽(下标间距离)*高(可存高度差):(i-pre-1)*(Math.min(height[i],height[pre])-height[cur])
//双指针法:寻找每个位置上的可堆积的雨水高度,即左右寻找水桶的最高边界,取最低值-底部高度
class Solution {
    public int trap(int[] height) {
        int sum= 0;
        //计算每一个位置可堆积的雨水高度,叠加
         int lheight, rheight;
        for(int i = 0; i < height.length; i++){
            lheight = 0;
            rheight = 0;
            for(int l = i-1; l >= 0; l--){
                lheight = Math.max(lheight,height[l]);
            }
            for(int r = i+1; r < height.length; r++){
                rheight = Math.max(rheight,height[r]);
            }
            int get = Math.min(lheight,rheight)-height[i];
            sum += get>0? get:0;
        }
        return sum;
    }
}


//动态规划:最快,按列计算存水量
class Solution {
    public int trap(int[] height) {
        int len = height.length;
        int[][] dp = new int[len+2][2];//初始值全为0,首尾添加虚拟节点可存水高度一定为0
        int sum= 0;
        for(int left = 1; left <= len; left++){
            dp[left][0] = Math.max(dp[left-1][0],height[left-1]);//左侧高度
            int right = len+2-1-left;
            dp[right][1] = Math.max(dp[right+1][1],height[right-1]);//右侧高度
        }
        for(int i = 1; i <= len; i++){
            int get = Math.min(dp[i][0],dp[i][1])-height[i-1];
            sum += get>0?get:0;
        }
        return sum;
    }
}

//单调栈:按行计算存水量
class Solution {
    public int trap(int[] height) {
        Stack<Integer> index = new Stack<>();
        int sum = 0;
        index.push(0);
        for(int i = 1; i < height.length; i++){
            int cur = index.peek();
            while(!index.isEmpty() && height[i] >= height[cur]){
                cur = index.pop();
                if(!index.isEmpty()){
                    int pre = index.peek();
                    sum += (i-pre-1)*(Math.min(height[i],height[pre])-height[cur]);
                    cur = pre;
                }               
            }
            index.push(i);
        }
        return sum;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值