【算法速刷(9/100)】LeetCode —— 42.接雨水

news/2024/11/13 20:05:24/

目录

自我解法

官方解法

解法一:动态规划、前后缀

解法二:单调栈

自我解法

这道题刚拿到的时候,第一时间的想法是将其想象成MC一样的方块世界,如何去生成水一样的去解决。后来发现有点复杂化了,因为题目只需要累计的结果数字,不需要额外的东西,但因为先入为主的观念,我还是选择了从低到高从左到右依次遍历的模拟法,这种方法的复杂度基本上是O(N * MaxHeight),实际也是十分低效,但私以为思路也是值得一分享,最后用例通过319/323。

class Solution {
public:int trap(vector<int>& height) {//从低到高从右向左打射线,找到间隔布置的两个方块,计算间隔,累加到结果上int res = 0;int n = height.size();int maxHeight = *max_element(height.begin(), height.end());for(int y = 1; y <= maxHeight; y++){int lastBlockX = -1;for(int x = 0; x < n; x++){if(height[x] >= y){if(lastBlockX != -1){res += x - lastBlockX - 1;}lastBlockX = x;}}}return res;}
};

官方解法

官方的解法从数学角度考虑,并没有被这张图迷倒,而是在一维上解决问题,从这个角度出发,怎么也不会搞出来O(n * MaxHeight)的复杂度。

解法一:动态规划、前后缀

正所谓问题的关键在于找到关键的问题,这道题的关键也就是关键的问题:如何在数组的某个位置上计算其位置上能积累的水的高度?

实际上给定位置上能积水的高度就是“左边最高高度和右边最高高度”中的最小值。

我们可以通过构造两个数组来分别记录一个位置上左边和右边的最高高度,O(2N)的复杂度即可完成构造。注意构造的数组的值,不应低于当前位置的高度,假设左边高度始终低于当前高度,则在数组中记录为当前位置的高度,这样可以保证构造的数组减去原数组中当前位置高度不会出现负值。

最后指定一个位置,其能积累的水高度就是 min(leftMaxH, rightMaxH) - currentH

这个算式的值域 >= 0

最后时间复杂度即为O(3n) = O(n),漂亮滴很呐

class Solution {
public:int trap(vector<int>& height) {//预处理每个方块的左边和右边的最大数//该区块的纵向存水数量为左右墙中最低的高度减去自身int n = height.size();vector<int> leftMax(n);leftMax[0] = height[0];for(int i = 1; i < n; i++)leftMax[i] = max(leftMax[i - 1], height[i]);vector<int> rightMax(n);rightMax[n - 1] = height[n - 1];for(int i = n - 2; i >= 0; i--)rightMax[i] = max(rightMax[i + 1], height[i]);int res = 0;for(int i = 0; i < n; i++)res += min(leftMax[i], rightMax[i]) - height[i];return res;}
};

解法二:单调栈

除了上面比较常见的做法,还有就是使用单调栈。直观来说,通过维护一个单调递减的栈,可以通过进栈出栈来识别哪里是洼地,进栈则坡的方向是↘,出栈则坡的方向是↗。遇到递增则进行出栈操作,两个坐标之间的间隔必为空,即可以储水,累加到结果中。

需要注意的是,在出栈的操作中,需要三个高度

  • 第一个高度(栈顶),代表需要忽略的高度,因为是上一次已经处理过的,不忽略会导致重复累加
  • 第二个高度(次栈顶),代表当前蓄水的左边界高度,本次循环中不出栈,等下一次出栈。
  • 第三个高度(当前遍历到的),代表当前蓄水的右边界高度,尚未入栈。

如果是第一次做的话,还是很难想到这样写的,Debug会疯掉哒

class Solution {
public:int trap(vector<int>& height) {stack<int> stk;int n = height.size();int res = 0;for(int i = 0; i < n; i++){while(!stk.empty() && height[i] > height[stk.top()]){int top = stk.top();stk.pop();if(stk.empty())break;int left = stk.top();int space = i - left - 1;int h = min(height[left], height[i]) - height[top];res += space * h;}stk.push(i);}return res;}
};


http://www.ppmy.cn/news/1546367.html

相关文章

YOLO即插即用---PConv

Run, Don’t Walk: Chasing Higher FLOPS for Faster Neural Networks 论文地址&#xff1a; 1. 论文解决的问题 2. 解决问题的方法 3. PConv 的适用范围 4. PConv 在目标检测中的应用 5. 评估方法 6. 潜在挑战 7. 未来研究方向 8.即插即用代码 论文地址&#xff1a; …

【ChatGPT】 让ChatGPT模拟客户服务对话与应答策略

让ChatGPT模拟客户服务对话与应答策略 在客户服务领域&#xff0c;提供一致、礼貌、且有效的应答至关重要。通过设计合适的Prompt&#xff0c;ChatGPT可以用来模拟客户服务对话&#xff0c;帮助团队提升应对客户的能力。本指南将展示如何设计Prompt&#xff0c;让ChatGPT在客户…

Linux(CentOS)安装 Nginx

CentOS版本&#xff1a;CentOS 7 Nginx版本&#xff1a;1.24.0 两种安装方式&#xff1a; 一、通过 yum 安装&#xff0c;最简单&#xff0c;一键安装&#xff0c;全程无忧。 二、通过 编译源码包安装&#xff0c;需具备配置相关操作。 一、通过 yum 安装 需要 root 权限&…

ubuntu22.04 安装ffmpeg

ubuntu22.04 安装ffmpeg wget https://ffmpeg.org/releases/ffmpeg-7.0.1.tar.xz tar -xvf ffmpeg-7.0.1.tar.xz sudo apt-get install gcc g cmake make pkgconf -y mkdir -p ~/util/ffmpeg/lib cd ffmpeg-7.0.1 ./configure --prefix"/home/ip3/util/ffmpeg" --en…

机器学习——排序特征(Ranking Features)原理详解

排序特征&#xff08;Ranking Features&#xff09; 在机器学习中用于排序任务。它们的核心思想是利用特征来判断不同样本的相对顺序&#xff0c;这在信息检索、推荐系统等领域十分常见。排序特征背后的底层原理和实现方式相对复杂&#xff0c;下面从底层原理、常用方法以及代码…

案例精选 | 河北省某检察院安全运营中异构日志数据融合的实践探索

河北省某检察院是当地重要的法律监督机构&#xff0c;肩负着维护法律尊严和社会公平正义的重要职责。该机构依法独立行使检察权&#xff0c;负责对犯罪行为提起公诉&#xff0c;并监督整个诉讼过程&#xff0c;同时积极参与社会治理&#xff0c;保护公民权益&#xff0c;推动法…

WPF Prism中的区域(Region)管理

Prism框架中的区域&#xff08;Region&#xff09;管理是一个核心功能&#xff0c;它允许开发者将用户界面划分为多个逻辑区域&#xff0c;每个区域可以动态地加载和显示不同的视图&#xff08;View&#xff09;。以下是Prism区域管理的一些关键特性和使用方法&#xff1a; 1.…

Go语言中的`io.Copy`函数:高效的数据复制解决方案

在Go语言中&#xff0c;io.Copy函数是一个强大而高效的工具&#xff0c;用于将数据从一个io.Reader复制到一个io.Writer。这篇文章将深入探讨io.Copy函数的工作原理、使用方法及其在实际应用中的优势。无论您是后端开发人员还是对Go语言感兴趣的程序员&#xff0c;这篇文章都将…