面试热题(接雨水问题)

给定 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;
    }
相关推荐
西瓜er3 分钟前
JAVA:Spring Boot 集成 FFmpeg 实现多媒体处理
java·spring boot·ffmpeg
你总是一副不开心的样子(´ . .̫ .7 分钟前
一、十天速通Java面试(第三天)
java·面试·职场和发展·java面试
迎風吹頭髮17 分钟前
UNIX下C语言编程与实践63-UNIX 并发 Socket 编程:非阻塞套接字与轮询模型
java·c语言·unix
我是华为OD~HR~栗栗呀19 分钟前
23届考研-Java面经(华为OD)
java·c++·python·华为od·华为·面试
Javatutouhouduan37 分钟前
Java程序员如何深入学习JVM底层原理?
java·jvm·java面试·后端开发·java架构师·java程序员·互联网大厂
王嘉俊9251 小时前
设计模式--享元模式:优化内存使用的轻量级设计
java·设计模式·享元模式
2301_803554522 小时前
C++联合体(Union)详解:与结构体的区别、联系与深度解析
java·c++·算法
EnCi Zheng2 小时前
SpringBoot 配置文件完全指南-从入门到精通
java·spring boot·后端
烙印6012 小时前
Spring容器的心脏:深度解析refresh()方法(上)
java·后端·spring
为什么我不是源代码2 小时前
JPA读取数据库离谱问题-No property ‘selectClassByName‘ found-Not a managed type
java·sql