LeetCode 热题 100 | 双指针(下)

目录

[42. 接雨水](#42. 接雨水)

[1 方法一:我的方法](#1 方法一:我的方法)

[2 方法二:动态规划](#2 方法二:动态规划)

[3 方法三:双指针](#3 方法三:双指针)


菜鸟做题第一周,语言是 C++

42. 接雨水

1 方法一:我的方法

++Warning:这是我的智障做法,请勿模仿++

我只能说它教会了我 "&&" 是从左到右进行判断的,第一个不成立就不会看第二个了。当判断条件顺序写反时,即使我写了防止指针越界的约束条件,它也压根看不到。最后就会这样:

解题思路:

  1. 正向遍历,算每个下标的积水高度(绿色面积)
  2. 反向遍历,算每个下标的积水高度(红色面积)
  3. 取每个下标的积水高度的较小值即为真实积水高度(阴影面积)

力扣官方说明图:

cpp 复制代码
class Solution {
public:
    int trap(vector<int>& height) {
        int left = 0, right = 0, rain = 0;
        unordered_map<int, int> forward, backward;

        // 正向遍历
        while (left <= height.size() - 1) {
            while (right <= height.size() - 1 && height[left] >= height[right])
                ++right;

            if (left + 1 <= height.size() - 1 && height[left] > height[left + 1]) {
                int temp = left + 1;
                while (temp < right) {
                    forward[temp] = height[left] - height[temp];
                    ++temp;
                }
                left = right - 1;
            }
            ++left;
        }

        // 反向遍历
        left = height.size() - 1, right = height.size() - 1;
        while (right >= 0) {
            while (left > 0 && height[left] <= height[right])
                --left;

            if (right - 1 >= 0 && height[right] > height[right - 1]) {
                int temp = right - 1;
                while (temp > left) {
                    backward[temp] = height[right] - height[temp];
                    --temp;
                }
                right = left + 1;
            }
            --right;
        }

        // 计算雨水
        for (int i = 0; i < height.size() - 1; ++i) {
            rain += min(forward[i], backward[i]);
        }
        return rain;
    }
};
2 方法二:动态规划

解题思路:

  1. 正向遍历,算每个区域的局部最大高度(绿色)
  2. 反向遍历,算每个区域的局部最大高度(红色)
  3. 取每个下标的最大高度的较小值再减该下标的高度
  4. 总和为 rain 积水量

事实证明是我没有彻底理解官方题解的思路,所以才搞出了方法一这种智障解法。

力扣官方说明图:

cpp 复制代码
class Solution {
public:
    int trap(vector<int>& height) {
        int n = height.size();
        vector<int> leftMax(n), rightMax(n);
        if (n == 0) return 0;

        // 正向遍历
        leftMax[0] = height[0];
        for (int i = 1; i < n; ++i) {
            leftMax[i] = max(leftMax[i - 1], height[i]);
        }

        // 反向遍历
        rightMax[n - 1] = height[n - 1];
        for (int i = n - 2; i >= 0; --i) {
            rightMax[i] = max(rightMax[i + 1], height[i]);
        }

        // 计算雨水
        int rain = 0;
        for (int i = 0; i < n; ++i) {
            rain += min(leftMax[i], rightMax[i]) - height[i];
        }

        return rain;
    }
};
3 方法三:双指针

思路说明:

方法二是完成正向遍历和反向遍历后才来计算 rain 积水量,而方法三是利用双指针一左一右同时开始遍历,并且可以直接计算 rain 积水量。

由于每次移动前都立即计算了:

cpp 复制代码
leftMax = max(leftMax, height[left]);
rightMax = max(rightMax, height[right]);

所以下面的两个不等式成立:

  • 若 heightleft < heightright,则必有 leftMax < rightMax
  • 若 heightleft > heightright,则必有 leftMax > rightMax

那么就可以直接计算 rain 积水量了:

  • 若 heightleft < heightright,则 rain += leftMax - heightleft
  • 若 heightleft > heightright,则 rain += rightMax - heightright

一开始我觉得很难理解,但是动动笔写一下,就知道不等式成立了。比如,对于第一个不等式,就可能存在 heightleft < leftMax < rightMax < heightright 或者 leftMax < heightleft < rightMax < heightright 等情形,它们都会使不等式成立。

cpp 复制代码
class Solution {
public:
    int trap(vector<int>& height) {
        int n = height.size(), rain = 0;
        if (n == 0) return 0;

        int leftMax = 0, rightMax = 0;
        int left = 0, right = n - 1;

        while (left != right) {
            leftMax = max(leftMax, height[left]);
            rightMax = max(rightMax, height[right]);
            if (height[left] < height[right]) {
                rain += leftMax - height[left];
                ++left;
            } else {
                rain += rightMax - height[right];
                --right;
            }
        }

        return rain;
    }
};
相关推荐
专注仿真3 小时前
ACM算法
算法·深度优先
顺顺 尼6 小时前
linux 进程信号(上)
linux·c++·算法
罗西的思考6 小时前
[Agent Memory / 强化学习] MemPO源码学习笔记 ---(5)--- GRPO
人工智能·算法·机器学习
richard_yuu6 小时前
动态规划:强化学习的「数学基础」,从 MDP 到值迭代
深度学习·神经网络·算法·yolo·机器学习·动态规划
mmmmath_37 小时前
LeetCode.225.用队列实现栈
算法
Elaine3367 小时前
数据结构与算法-程序
数据结构·python·算法·计算机基础·编程基础
2601_965742227 小时前
布局GEO AI本地营销,我重点看这几个细节
大数据·人工智能·算法·ai·新媒体运营
EatFan7 小时前
AI Agent 上生产前先加三道闸门:审批、限权、可回放的工程实践
人工智能·python·算法·多智能体·ai agent·mcp·harness
思茂信息7 小时前
CST软件BCI仿真模型及仿真案例
开发语言·单片机·嵌入式硬件·算法·emc
Persistent的粽子!7 小时前
双指针算法:最大盛水容器
c++·算法·leetcode