42. 接雨水(相向双指针/前后缀分解),一篇文章讲透彻

给定一个数组,代表柱子的高度

求出下雨之后,能接的水有多少单位。我们将每一个柱子想象成一个水桶,看他能接多少水

以这个水桶为例,他所能接的水取决于左边的柱子的最大高度和右边柱子的最大高度,因为只有柱子高的时候水才不会流出去,就比如红色的水桶他能接的水 = min(左边柱子最大高度,右边柱子最大高度) - 柱子的高度 = 1

那么,求出了所有的水桶能接的水,求和就是我们的答案了,那么怎么能知道第i个柱子左右两侧柱子的最大值呢。这里我们需要借助两个数组,pre_max,suf_max,分别表示前缀最大值和后缀最大值,前置最大值等于 = max(pre_max[i-1],height[i]),suf_max同理。

如下图:

代码:

cpp 复制代码
class Solution {
public:
    //一个水桶能接的水取决于左边柱子的最大高度和右边柱子的最大高度,因为这样水才不会流出
    //前后缀分解
    //第i个宽度为1的桶可以接的水 = min(此处的前缀最大值,此处的后缀最大值) - height[i] 
    int trap(vector<int>& height) {
        int n = height.size();
        int pre_max[n],suf_max[n];
        pre_max[0] = height[0];
        for (int i = 1;i < n;i++) {
            pre_max[i] = max(pre_max[i - 1],height[i]);
        }
        suf_max[n - 1] = height[n - 1];
        for (int i = n - 2;i >= 0;i--) {
            suf_max[i] = max(suf_max[i + 1],height[i]);
        }
        int ans = 0;
        for (int i = 0;i < n;i++) {
            ans += min(pre_max[i],suf_max[i]) - height[i];
        }
        return ans;
    }
};

时间复杂度:求pre_max和suf_max都是一次遍历,所以时间复杂度是O(n)的

空间复杂度:借助了两个数组,所以是O(n)的

本题目时间复杂度已经最优了,那空间复杂度是否可以优化呢?注意到,如果我们求出了一个水桶的一部分前缀最大值和后缀最大值,此时前缀最大值小于后缀最大值,此时水桶的接水量就是前缀最大值-height[i],因为水是否会流出取决于较短的木板。这样我们用一个变量即可替代一个数组,将空间复杂度优化到了O(1)。

具体代码:

cpp 复制代码
class Solution {
public:
    
    int trap(vector<int>& height) {
        int n = height.size();
        int pre_max = 0,suf_max = 0;
        int left = 0, right = n - 1;
        int ans = 0;
        while (left <= right) {
            pre_max = max (pre_max,height[left]);
            suf_max = max (suf_max,height[right]);
            if (pre_max < suf_max) {
                ans += pre_max - height[left];
                left++;
            }else{
                ans += suf_max - height[right];
                right--;
            }
        }
        return ans;
    }
};
相关推荐
孞㐑¥1 分钟前
算法—滑动窗口
开发语言·c++·经验分享·笔记·算法
历程里程碑5 分钟前
Linux 3 指令(3):进阶指令:文件查看、资源管理、搜索打包压缩详解
linux·运维·服务器·c语言·数据结构·笔记·算法
咋吃都不胖lyh20 分钟前
GBDT 中的前向分布算法和贪婪学习
学习·算法
leo__52023 分钟前
CLEAN算法仿真程序,用于雷达信号中的杂波抑制
算法
一分之二~34 分钟前
二叉树--求最小深度(迭代和递归)
数据结构·c++·算法·leetcode·深度优先
老鼠只爱大米34 分钟前
LeetCode经典算法面试题 #24:两两交换链表中的节点(迭代法、递归法等多种实现方案详细解析)
算法·leetcode·链表·递归·双指针·迭代·链表交换
mjhcsp35 分钟前
挑战训练一个 AlphaZero 五子棋
算法·洛谷
Word码1 小时前
leetcode260.只出现一次的数字III
算法
MM_MS1 小时前
Halcon图像采集助手、ROI操作和画图、ROI实现区域与轮廓之间的相互转换、区域的交集差集取反
图像处理·人工智能·数码相机·算法·目标检测·计算机视觉·视觉检测
智者知已应修善业1 小时前
【输出一个N*N的01矩阵,表示最后的汉字点阵图】2024-10-22
c语言·数据结构·c++·经验分享·笔记·算法·矩阵