力扣热题100--day7(c++版)

题目要求:接雨水

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

解题思路:

       联想到了我之前做过的另一道求盛水最多容器的题目,一眼看出使用双指针,通过同时从数组的两端向中间靠拢,利用两个指针分别比较当前左右指针指向的柱子高度,然后就直接求出接水量。但奈何本人能力有限也只知道要用双指针,具体如何实现完全没思路。于是乎只能考虑其他啥办法了。(没做过的可以先尝试做一下,可能做完之后就有思路了,参考链接:https://leetcode.cn/problems/container-with-most-water/description/?envType=study-plan-v2&envId=top-100-liked

1.从左向右遍历法(思路错误,忽略解法1)

        我的思路是从左往右遍历,通过找到每个柱子 i 之后第一个可以形成接水区域的柱子 jheight[j] >= height[i]),然后计算 ij 之间的接水量。更新 i = j,继续遍历,直到找到所有的接水区域。

实现代码

class Solution {
public:
    int trap(vector<int>& height) {
        int n = height.size();
        if (n<3) return 0;

        int res=0;
        
        for (int i=0; i<n-1; i++){
            for (int j=i+1; j<n; j++){
                if (height[i]<=height[j]){
                    int minheight = min(height[i], height[j]);
                    for (int k=i+1; k<j; k++){
                        res += (minheight - height[k]);
                    }
                    i = j-1;
                    break;
                }
            }  
        }
        return res;
    }
};

其实错误的根源在于使用了 i = j - 1 来跳过位置 j,并没有考虑像 [4, 2, 3] 这样的情况。这样会导致 i 没有正确处理 j 所在的接水区域,导致错误的结果。但是实在能力有限没有想到很好的方法去解决这个问题,看看之后能力变强之后能不能解决吧,先浅浅挖一个坑。

2.双指针法

具体思路:

(1)初始化指针和变量:

leftright 分别指向数组的两端,表示当前考察的左右两边的柱子。

left_maxright_max 分别记录从左边和右边看到的最高柱子的高度。

water 变量用于存储最终的积水量。

(2)核心逻辑:

使用 while (left < right),当左指针小于右指针时,循环继续。

比较 height[left]height[right] 的值:

如果 height[left] < height[right],表示当前左边的柱子较矮,接水量由左边的 left_max 决定。如果当前 height[left] >= left_max,更新 left_max;否则计算积水量 left_max - height[left],然后左指针右移。

如果 height[left] >= height[right],则由右边的 right_max 决定接水量,计算方式类似,右指针左移。

(3)结束条件:

leftright 相遇时,所有的水都已经计算完毕,最终返回积水量 water。

具体代码:

class Solution {
public:
    int trap(vector<int>& height) {
        if (height.empty()) return 0;  // 如果数组为空,直接返回 0
        
        int left = 0, right = height.size() - 1;  // 初始化双指针
        int left_max = 0, right_max = 0;  // 分别记录左边和右边的最高柱子
        int water = 0;  // 记录总的积水量
        
        while (left < right) {
            if (height[left] < height[right]) {
                if (height[left] >= left_max) {
                    left_max = height[left];  // 更新左边最高柱子
                } else {
                    water += left_max - height[left];  // 计算左边能接的水
                }
                ++left;  // 移动左指针
            } else {
                if (height[right] >= right_max) {
                    right_max = height[right];  // 更新右边最高柱子
                } else {
                    water += right_max - height[right];  // 计算右边能接的水
                }
                --right;  // 移动右指针
            }
        }
        
        return water;  // 返回总的积水量
    }
};

        双指针法通过同时从数组的两端向中间靠拢,利用两个指针分别维护左边和右边的最大高度。每次比较当前左右指针指向的柱子高度,并计算出可以接的水量。这种方法避免了不必要的重复计算,每个柱子最多访问一次。对比我的错误思路(如果可以实现的话),其效率高,时间复杂度 O(n),因为只需要遍历一次数组,两个指针分别从数组的两端向中间靠拢,每个位置最多访问一次;空间复杂度 O(1),只使用了常量的额外空间来存储指针和最大高度。每次根据左右指针的高度移动较小的一侧,动态更新左右两侧的最大高度,逐步计算接水量。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值