LeetCode42 接雨水

题目

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

示例 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

方法

动态规划法

分别用left和right数组计算左边和右边的最大边界值,然后取左右的最小值减去本身占用的面积计算当前坐标下积攒的面积,然后累加

  • 时间复杂度:O(n)
  • 空间复杂度:O(n)
class Solution {
    public int trap(int[] height) {
        int length = height.length;
        int[] left = new int[length];
        int[] right = new int[length];
        left[0] = height[0];
        for(int i=1;i<length;i++){
            left[i] = Math.max(left[i-1],height[i]);
        }
        right[length-1] = height[length-1];
        for(int i=length-2;i>=0;i--){
            right[i] = Math.max(right[i+1],height[i]);
        }
        int area = 0;
        for(int i=0;i<length;i++){
            area += Math.min(left[i],right[i])-height[i];
        }
        return area;
    }
}

单调栈法

单调栈从top到底存储从小到大的连续值,水平一层一层的计算有效值

  • 时间复杂度:O(n)
  • 空间复杂度:O(n)
class Solution {
    public int trap(int[] height) {
        int length = height.length,ans = 0;
        Deque<Integer> stack = new LinkedList<>();
        for(int i=0;i<length;i++){
            while (!stack.isEmpty()&&height[i]>height[stack.peek()]){
                int top = stack.poll();
                if(!stack.isEmpty()){
                    int left = stack.peek();
                    int curWidth = i-left-1;
                    int curHeight = Math.min(height[i],height[left])-height[top];
                    ans += curHeight*curWidth;
                }
            }
            stack.push(i);
        }
        return ans;
    }
}

双指针法

双指针leftMax和rightMax从两侧保存左边和右边的最大值
leftMax<rightMax,说明两边的最小边界高为leftMax,可以更新左边的值
leftMax>=rightMax,说明两边的最小边界高为rightMax,可以更新右边的值

  • 时间复杂度:O(n)
  • 空间复杂度:O(1)
class Solution {
    public int trap(int[] height) {
        int length = height.length,ans = 0;
        int leftMax = 0,rightMax = 0;
        int l = 0,r = length-1;
        while (l<r){
            leftMax = Math.max(leftMax,height[l]);
            rightMax = Math.max(rightMax,height[r]);
            if(leftMax<rightMax){
                ans += leftMax - height[l];
                l++;
            }else{
                ans += rightMax - height[r];
                r--;
            }
        }
        return ans;
    }
}
posted @   你也要来一颗长颈鹿吗  阅读(20)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示