42.接雨水LeetCode

题目来源LeetCode第42题
在这里插入图片描述
根据别人大佬思想,自己慢慢领悟后总结,java编写出来的四个解该题的方法,我也是菜鸟一枚,写了很久的,所以做个笔记大家分享,大家指出不足,麻烦点个赞吧,谢谢
首先是用于测试的主函数

    public static void main(String[] args) {
        int[] height=new int[]{6,8,5,0,0,6,5};
        System.out.println(new Solution().trap1(height));
        System.out.println(new Solution().trap2(height));
        System.out.println(new Solution().trap3(height));
        System.out.println(new Solution().trap4(height));
    }

method1
思路:

  • 按层分割,在每一层遍历遍每堵墙
  • 若当前墙小于该层则遇到积水沟,则addWater++;(初始条件不可刷新addWater)
  • 若当前墙大于该层,则收集该积水sum+=addWater;
  • 直至每层的每堵墙判断完
  • 时间复杂度O(m*n)
  • 空间复杂度O(1)

在这里插入图片描述

   /*
    获取层数
     */
    public int getFloors(int[] height){
        int min=0,max=0;
        for (int i=0;i<height.length;i++){
            if(height[i]>=max){
                max=height[i];
            }else if(height[i]<=min){
                min=height[i];
            }
        }
        return max-min;
    }
    /**
     * 按层数求积水
     * @param height
     * @return
     */
    public int trap1(int[] height) {
        int sum=0;
        int floors=getFloors(height);
        //每一层搜索积水
        for(int floor=1;floor<=floors;floor++){
            int addWater=0;
            //是否可以刷新addWater
            boolean refreshAble=false;
            for (int i=0;i<height.length;i++){

                if(refreshAble&&height[i]<floor){
                    addWater++;
                }else if(height[i]>=floor){
                    sum+=addWater;
                    //addWater用了之后归零
                    addWater=0;
                    refreshAble=true;
                }
            }
        }
        return sum;
    }

method2
思路:

  • 遍历每堵墙,并且找出每堵墙的左右边最高墙(left_max和right_max),找出后比较两堵墙,选择一个较矮的墙between_min,然后判断当前墙是否存在积水( if(between_min>height[i]) ),若存在则收集在当前墙处的积水sum+=(between_min-height[i]);
  • 上述步骤直至每堵墙判断完
  • 时间复杂度O(n2)
  • 空间复杂度O(1)
    在这里插入图片描述
     /**
     * 按列(高度)求积水
     * @param height
     * @return
     */
    public int trap2(int[] height){
        int sum=0;
        //遍历每堵墙height[i],并且找出每堵墙上是否有积水
        //两边的墙不用考虑,因为边界不存在积水
        for (int i=1;i<height.length-1;i++){
            int left_max=0,right_max=0;
            //找出当前墙左边最高的墙
            for (int left=0;left<i;left++){
                if(height[left]>left_max){
                    left_max=height[left];
                }
            }
            //找出当前墙左边最高的墙
            for (int right=i+1;right<height.length;right++){
                if(height[right]>right_max){
                    right_max=height[right];
                }
            }
            //两堵最高墙之间较矮的墙  如果较矮墙高于当前墙 则计算较矮的墙与当前墙之间的差(积水深度)
            int between_min=Math.min(left_max,right_max);
            if(between_min>height[i]){
                sum+=(between_min-height[i]);
            }
        }
        return  sum;
    }

method3
思路:

  • 我已在代码注释中说明了,如下
  • 时间复杂度O(n)
  • 空间复杂度O(n)
     /**
     * 同第二种解法,只不过寻找当前墙的左边最高墙与右边最高墙时,方法简化了,利用动态规划寻找,节约时间复杂度
     * 寻找的思路:
     * 如果(当前墙)的(左边墙)的(左边最高墙)比(左边墙)高,那么(当前墙)的(左边最高墙) = (左边墙)的(左边最高墙),反之为(当前墙)的(左边最高墙) = (左边墙)
     * 寻找右边最高墙的思路与上面一样
     * 把每堵当前墙的左右边最高墙,分别保存在两个数组里left_max[] right_max[]
     * @param height
     * @return
     */
    public int trap3(int[] height){
        int sum=0;
        int[] left_max=new int[height.length];
        int[] right_max=new int[height.length];
        //最左边的墙不遍历
        for (int left=1;left<height.length-1;left++){
            left_max[left]=Math.max(left_max[left-1],height[left-1]);
        }
        //最右边的墙不遍历
        for (int right=height.length-2;right>=0;right--){
            right_max[right]=Math.max(right_max[right+1],height[right+1]);
        }
        //边界墙不存在积水,则排除
        for (int cur=1;cur<height.length-1;cur++){
            //求两堵最高墙之间较小的墙between_min
            int between_min=Math.min(left_max[cur],right_max[cur]);
            //如果between_min比当前墙高,则存在积水
            if(between_min>height[cur]){
                sum+=(between_min-height[cur]);
            }
        }
        return sum;
    }

method4
思路:

  • 代码注释已说明,如下
  • 时间复杂度O(n)
  • 空间复杂度O(n)
     /**
     * 利用栈
     * @param height
     * @return
     */
    public int trap4(int[] height){
        int sum=0;
        Stack<Integer> stack=new Stack<Integer>();
        int cur=0;
        while (cur<height.length){
            //判断当前墙是否大于栈顶(存在积水沟),1、若ture,则弹出栈顶(加一个栈判空条件),计算新的栈顶与当前墙之间的积水
            //若当前墙也大于新的栈顶重复1操作,2、反之跳出循环,把当前墙入栈
            while (!stack.empty()&&height[cur]>height[stack.peek()]){
                int peek=height[stack.pop()];
                //弹出后再次判断栈是否为空,空则break
                if(stack.empty()){
                    break;
                }
                //计算当前墙与新的栈顶之间的距离
                int width=cur-stack.peek()-1;
                //获取当前墙与新的栈顶之间较矮的墙
                int min=Math.min(height[stack.peek()],height[cur]);
                //计算积水
                sum+=width*(min-peek);
            }
            stack.push(cur);
            cur++;
        }
        return sum;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值