接雨水----解

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


前言


一、思路

写一半忘记这是双指针了

java 复制代码
class Solution {
    public int trap(int[] height) {

            int max = height[0]; // 初始化为第一个元素
            for (int i = 1; i < height.length; i++) {
                if (height[i] > max) {
                    max = height[i];
                }
            }

            int count=0;
            for(int i=1;i<max;i++){
                s1:for(int j=0;j<height.length;j++){
                    while(j==0 && height[j]<=0){//找到第一个边界 >i
                        continue s1;
                    }
                    if(j+1<height.length && height[j+1]<i){//找第一层空格
                        count++;
                        continue ;}
                    if(j==height.length-1 && height[j]==0){
                        return 0;
                    }

                }

            }
            return count;
        }
}

像俄罗斯方块一样,一层一层数,好在他这个盖不了顶。

二、加入双指针

按层计算,时间复杂度是O(N*柱子高度),虽然是没到O(N2),但是实际表现会更差。

java 复制代码
class Solution {
    public int trap(int[] height) {

            int max = height[0]; // 初始化为第一个元素
            for (int i = 1; i < height.length; i++) {
                if (height[i] > max) {
                    max = height[i];
                }
            }

            int count=0;
            for(int i=1;i<=max;i++){
                s1:for(int j=0;j<height.length;j++){
                    int right=j+1,tmp=0;
                    boolean flag=false;
                    while(height[j]<i){//找到第一个边界 >i
                        continue s1;
                    }
                    while(right<height.length){
                        if(height[right]<i){
                            tmp++;
                            right++;
                        }else{
                            flag=true;
                            count+=tmp;
                            tmp=0;
                            break;
                        }
                    }
                    // if(j+1<height.length && height[j+1]<i){//找第一层空格
                    //     count++;
                    //     continue ;}
                    if(j==height.length-1 && height[j]==0){
                        return 0;
                    }

                }

            }
            return count;
        }
}

三、在二的基础上优化--双指针

想法很简单,就是按层扫变成减法。从上往下条状减,不小心抄多了,反正是0ms

第二次看的时候有点纠结,不太理解左右哪边先减,后来想明白了,先从短的那边算起,保持顺序性。

java 复制代码
class Solution {
    public int trap(int[] height) {
        // 1. 修复 Bug:处理空数组或长度不足 3 的情况(无法接水)
        if (height == null || height.length < 3) {
            return 0;
        }

        int left = 0;
        int right = height.length - 1;
        int leftMax = 0;  // 记录左边遇到的最高柱子
        int rightMax = 0; // 记录右边遇到的最高柱子
        int count = 0;    // 接水量

        // 2. 双指针向中间逼近
        while (left < right) {
            // 核心逻辑:哪边的柱子矮,哪边就是"短板",水能接多少取决于短板
            if (height[left] < height[right]) {
                if (height[left] >= leftMax) {
                    leftMax = height[left]; // 遇到更高的柱子,更新最大值,不接水
                } else {
                    count += leftMax - height[left]; // 当前柱子低于左边最大值,可以接水
                }
                left++; // 左指针向右移
            } else {
                // 处理右边(逻辑同上)
                if (height[right] >= rightMax) {
                    rightMax = height[right];
                } else {
                    count += rightMax - height[right];
                }
                right--; // 右指针向左移
            }
        }
        return count;
    }
}

四、Dp入门

先定义,再写基本式,再带入初值,最后让程序计算:

dp[n] 上n级台阶的解法

dp[n]=dp[n-1]+dp[n-2];

dp[1]=1,dp[2]=2

对于这题:

从左往右扫一次,从右往左扫一次,左右中小的那个减当前值

java 复制代码
class Solution {
    public int trap(int[] height) {
        int n = height.length;
        if (n <= 2) return 0;

        // 1. 定义 DP 数组
        int[] left_max = new int[n];
        int[] right_max = new int[n];

        // 2. 初始化 & 从左往右填表
        left_max[0] = height[0];
        for (int i = 1; i < n; i++) {
            left_max[i] = Math.max(left_max[i - 1], height[i]);
        }

        // 3. 从右往左填表
        right_max[n - 1] = height[n - 1];
        for (int i = n - 2; i >= 0; i--) {
            right_max[i] = Math.max(right_max[i + 1], height[i]);
        }

        // 4. 计算结果
        int ans = 0;
        for (int i = 0; i < n; i++) {
            // 木桶效应:取两边最小的,减去自己的高度
            ans += Math.min(left_max[i], right_max[i]) - height[i];
        }
        return ans;
    }
}

五、单调栈入门

从下往上入栈,从上往下弹出;单调递增和递减都积不了水

这里想的是,递减,然后突然碰到高个,然后就可以积水,然后右边的板就是高个,左边的板是最大值,然后计算是从递减的最小值开始的,由于是递减的,所以栈顶是小值,也就是横着的最底一层(就象数格子一样,横着一排数完),慢慢变大就慢慢往上


总结

困难题就不追求那么多了,一不小心抄多了。

对我来说Dp和栈都比较有挑战性,栈比较怪,或许公司会问。

相关推荐
洛水水3 小时前
【力扣100题】23. 螺旋矩阵
算法·leetcode·矩阵
Tisfy5 小时前
LeetCode 2553.分割数组中数字的数位:模拟(maybe+翻转)——java也O(1)
java·数学·算法·leetcode·题解·模拟·取模
Controller-Inversion6 小时前
42. 接雨水
数据结构·算法·leetcode
Controller-Inversion6 小时前
33. 搜索旋转排序数组
数据结构·算法·leetcode
驼同学.6 小时前
【求职季】LeetCode Hot 100 渐进式扫盲手册(Python版)
python·算法·leetcode
宵时待雨6 小时前
优选算法专题6:模拟
数据结构·c++·算法·leetcode·职场和发展
Liangwei Lin6 小时前
LeetCode 35. 搜索插入位置
数据结构·算法·leetcode
洛水水7 小时前
【力扣100题】22. 矩阵置零
算法·leetcode·矩阵
Liangwei Lin7 小时前
LeetCode 78. 子集
数据结构·算法·leetcode