面试热题(接雨水问题)

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

我们看到题的第一步,永远是对入参进行判断

java 复制代码
    public int trap(int[] height) {
        if (height == null) {
            return 0;
        }
          ...
    }

但是我们想想看,接雨水是不是和往桶里倒水的问题很像,倒入水的体积往往是由桶两边较低的那个高度决定的,这个问题亦是如此

由我们分析可知当数组的长度小于3的时候,是不可能接到雨水的,所以我们在判断入参条件的时候就可以这样写

java 复制代码
  public int trap(int[] height) {
        if (height == null || height.length < 3) {
            return 0;
        }
         ...
    }

刚才我们已经分析过了,一个位置的存储量只和最短的那一边有关系,边越长,我们固定位置上的存储量就越多,所以我们可以遍历每个位置,分别计算出各个位置上的存储量,再最后求和就完美的解决了本题

java 复制代码
        int count = 0;
        for (int i = 1; i < height.length; i++) {
            //找左边的最高值
            int lMax = 0;
            for (int j = 0; j < i; j++) {
                lMax = Math.max(lMax, height[j]);
            }
            //找到右边的最高值
            int rMax = 0;
            for (int j = i + 1; j < height.length; j++) {
                rMax = Math.max(rMax, height[j]);
            }
           }

好了,这样我们相对位置上的两边最高的边已经求出来了,只不过现在还存一个问题,如果,当前位置的高度如果大于较小的那边高度的话,是否还可有存储水量呢?

所以当前位置的高度如果大于两边最长的相对较小的边的高度,则不能进行存储水量,所以我们再对我们的代码进行完善

java 复制代码
  int count = 0;
        for (int i = 1; i < height.length; i++) {
            //找左边的最高值
            int lMax = 0;
            for (int j = 0; j < i; j++) {
                lMax = Math.max(lMax, height[j]);
            }
            //找到右边的最高值
            int rMax = 0;
            for (int j = i + 1; j < height.length; j++) {
                rMax = Math.max(rMax, height[j]);
            }
            if (Math.min(lMax, rMax) - height[i] > 0) {
                count += Math.min(lMax, rMax) - height[i];
            }
        }

这就完成了我们所谓hard题的接雨水问题了,这个题面试中还是经常问的,希望大家透析原理,面试无压力,下面给大家奉上整个代码,供大家参考借鉴

java 复制代码
    public int trap(int[] height) {
        if (height == null || height.length < 3) {
            return 0;
        }
        int count = 0;
        for (int i = 1; i < height.length; i++) {
            //找左边的最高值
            int lMax = 0;
            for (int j = 0; j < i; j++) {
                lMax = Math.max(lMax, height[j]);
            }
            //找到右边的最高值
            int rMax = 0;
            for (int j = i + 1; j < height.length; j++) {
                rMax = Math.max(rMax, height[j]);
            }
            if (Math.min(lMax, rMax) - height[i] > 0) {
                count += Math.min(lMax, rMax) - height[i];
            }
        }
        return count;
    }
相关推荐
会员源码网1 小时前
数字格式化陷阱:如何优雅处理 NumberFormatException
java
着迷不白1 小时前
Linux单用户模式密码修改与硬盘注释指南
面试
孔明click332 小时前
Sa-Token v1.45.0 发布 🚀,正式支持 Spring Boot 4、新增 Jackson3/Snack4 插件适配
java·sa-token·开源·springboot·登录·权限认证
有意义2 小时前
深度拆解分割等和子集:一维DP数组与倒序遍历的本质
前端·算法·面试
程序猿阿越2 小时前
Kafka4源码(二)创建Topic
java·后端·源码阅读
悟空码字2 小时前
Spring Boot 整合 MongoDB 最佳实践:CRUD、分页、事务、索引全覆盖
java·spring boot·后端
省长2 小时前
Sa-Token v1.45.0 发布 🚀,正式支持 Spring Boot 4、新增 Jackson3/Snack4 插件适配
java·后端·开源
NE_STOP3 小时前
MyBatis-动态sql与高级映射
java
后端AI实验室3 小时前
我把同一个需求分别交给初级程序员、高级程序员和AI,结果让我沉默了
java·ai
sTone873753 小时前
web后端开发概念: VO 和 PO
java·后端·架构