接雨水 , 给定二维图,能容多少水

42. 接雨水 - 力扣(LeetCode)

看着就是非常常规的题目,所以非常有必要掌握。

最少也把O(n^2)的方法写出来吧。力扣官方题解的三种方法O(n)都挺好,不过可能有点难读,在此经过学习,写一篇自己的通俗理解。

0.O(n^2)

每次只看单个格子,这个格子能放多少水呢?

只要左边和右边都比自己高,就能放水了。

所以对于每个格子,分别找到最左和最优最高的,(根据木桶原理。。)此格子能放的水就是较低的那个。

class Solution {
public:
    map<int,int>mm;
    int trap(vector<int>& height) 
    {
        int ret = 0;
        int n = height.size();
        for(int i=0;i<n-1;i++)
        {
            int r;
            int maxv = 0,maxo = 0;
            for(r=i+1;r<n;r++)
            {
                if(height[r]>=height[i])
                    break;

                if(height[r] >= maxv)
                {
                    maxv = height[r];
                    maxo = r;
                }
            }
            if(r>=n)
            {
                int aim = maxv;
                for(int j = i+1;j<maxo;j++)
                {
                    if(height[j]<aim)
                        ret += aim - height[j];
                }
                i = maxo-1;
            }
            else
            {
                int aim = min(height[i],height[r]);
                for(int j = i+1;j<r;j++)
                {
                    if(height[j]<aim)
                        ret += aim - height[j];
                }
                i = r-1;
            }
        }
        return ret;
    }
};

1.动态规划

其实跟背包问题差别蛮大的。

看题解这张图其实就很好懂:

左往右遍历一次,右往左遍历一次,取覆盖区域并集即可。(哇这是动归吗)

class Solution {
public:
    map<int,int>mm;
    int trap(vector<int>& height) 
    {
        int n = height.size();
        vector<int>l(n),r(n);
        int tmp = 0;
        for(int i=0;i<n;i++)
        {
            tmp = max(tmp,height[i]);
            l[i] = tmp;
        }
        tmp = 0;
        for(int i=n-1;i>=0;i--)
        {
            tmp = max(tmp,height[i]);
            r[i] = tmp;
        }
        int ret = 0;
        for(int i=0;i<n;i++)
        {
            ret += min(l[i],r[i]) - height[i];
        }
        return ret;
    }
};

2.单调栈

是这样的一个解法。

如果多格高:

单调栈内放下标,他们的高度 从栈底到栈顶 是降低的。

直到遇见一个高的,那么栈顶的就可以作底去装水,高度为左边和右边较低者。

class Solution {
public:
    stack<int>sti;
    int trap(vector<int>& height) 
    {
        int n = height.size();
        int ret = 0;
        for(int i=0;i<n;i++)
        {
            while(sti.size()&&height[i] > height[sti.top()])
            {
                //这个是放水的平面
                int top = sti.top(); sti.pop();
                if(sti.size() == 0)break;//挨着的 | 上升的

                //补的是和左边这个高度差

                ret += (i-sti.top()-1) * (min(height[sti.top()],height[i]) - height[top]);
            }            
            sti.push(i);
        }
        return ret;
    }
};

3.双指针

和1类似,是对0的优化,不用每次都挨着找一遍。官方题解写法我看不太懂。但思想是明确的。

我们找左边最大 leftmax和右边最大 rightmax,那么中间就是容器能装水啦。

我们从低的一边向另一边走,遇到的格子能放的水都最多到低的这边的高度。

比如 leftmax <= rightmax ,左向右,每个格子都能装水到 leftmax。

直到遇见高边,且这个高边比右边最高还高,就可以从右向左了。

不然就一直往右装水:

class Solution {
    //其实右边有足够高的,左边底的绝对都能放进去水
public:
    int trap(vector<int>& height) 
    {
        int n = height.size();
        int l = 1,r = n-2;
        int leftmax = height[0],rightmax = height[n-1];
        int ret = 0;
        while(l<=r)
        {
            while(leftmax <= rightmax&&l<=r)
            {
                if(height[l] < leftmax)
                    ret += leftmax - height[l];
                else
                    leftmax = height[l];
                l++;
            }
            
            while(leftmax > rightmax&&l<=r)
            {
                if(height[r] < rightmax)
                    ret += rightmax - height[r];
                else
                    rightmax = height[r];
                r--;
            }
        }
        return ret;
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/561713.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

简单的LRU本地缓存实现-Java版本

文章目录 什么是缓存缓存的种类缓存的关键特性缓存的优势与挑战优势&#xff1a;挑战&#xff1a; 缓存的应用场景什么是LRUCacheLRU 缓存的工作原理核心操作为何选择 LRU使用场景 一个简单的LRU缓存实现相关资料基础资料 什么是缓存 缓存&#xff08;Cache&#xff09;是一种…

机器人课程教师面对的困境有哪些(补充)

唯有自救&#xff0c;唯有自强&#xff0c;方能有希望。 前序 距离这一篇博文发表已经快2年了…… 机器人课程教师面对的困境有哪些 至少从5年前就已经有需求减少&#xff0c;供给过剩的现象出现了。 为何在2019年之后应用型本科开设ROS课程优势消逝 案例 博客分享过工作…

VSCode 目录折叠展开、缩进深度设置

1、VSCode 目录折叠展开设置 运行 Visual Studio Code &#xff0c;按 Ctrl &#xff0c;打开设置 输入Explorer:Compact Folders&#xff0c;取消勾选 或者在设置文件上添加 "explorer.compactFolders": false2、VSCode 目录缩进深度设置 输入Workbench Tree:…

AI大模型日报#0420:开源模型击败GPT-4、西湖大学蛋白质通用大模型、GPT的七条经验

导读&#xff1a; 欢迎阅读《AI大模型日报》&#xff0c;内容基于Python爬虫和LLM自动生成。目前采用“文心一言”生成了每条资讯的摘要。 标题: 开源模型打败GPT-4&#xff01;LLM竞技场最新战报&#xff0c;Cohere Command R上线 摘要: GPT-4在LLM竞技场被开源模型Cohere的…

【开发问题记录】启动某个服务时请求失败(docker-componse创建容器时IP参数不正确)

问题记录 一、问题描述1.1 产生原因1.2 产生问题 二、问题解决2.1 找到自己的docker-compose.yml文件2.2 重新编辑docker-compose.yml文件2.3 通过docker-componse重新运行docker-compose.yml文件2.4 重新启动docker容器2.5 查看seata信息 一、问题描述 1.1 产生原因 因为我是…

在ubuntu20.04下迁移anaconda的目录,试验不行后,换成软连接

一、原因 随着不断的搭建不同的算法环境&#xff0c;原本在固态硬盘上安装的anaconda上占用空间越来越多。导致可用的固态硬盘空间越来越少&#xff0c;又因安装的环境太多&#xff0c;重新搭建比较费时费力。有没有直接将当前已经搭建好环境的anaconda 迁移到另外的目录呢&…

算法题解记录19+++回文链表(百日筑基)

题目描述&#xff1a; 难度&#xff1a;简单 给你一个单链表的头节点 head &#xff0c;请你判断该链表是否为回文链表。如果是&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,2,1] 输出&#xff1a;true示…

Kotlin语法快速入门--变量声明(1)

Kotlin语法入门–变量声明&#xff08;1&#xff09; 文章目录 Kotlin语法入门--变量声明&#xff08;1&#xff09;一、变量声明1、整型2、字符型3、集合3.1、创建array数组3.2、创建list集合3.3、不可变类型数组3.4、Set集合--不重复添加元素3.5、键值对集合Map 4、kotlin特有…

【Python系列】python 如何打印带时间的日志

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

【软件测试】正交表测试例题

【软件测试】正交表测试 例题1答案 例题2答案 例题3答案 例题1 很多Word编辑器都有字体修饰功能&#xff0c;可以将一个字加粗、倾斜、以及加上下划线。一个字可以同时被加粗和倾斜&#xff0c;也可以同时被倾斜和加下划线。三种因子Bold, Italic, Underline的效果可以任意组合…

累加(C语言)

一、题目&#xff1b; 二、N-S流程图&#xff1b; 三、运行结果&#xff1b; 四、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h>int main() {//初始化变量值&#xff1b;int i 0;int j 0;int n 5;int result 0;int sum 0;//运算&#…

【氧化镓】Ga2O3 MOSFET器件的单SEB机制TCAD研究

本文是一篇关于氧化镓(Ga2O3)金属氧化物半导体场效应晶体管(MOSFET)在单粒子烧毁(single event burnout, SEB)事件中的机制研究的文章。文章通过使用技术计算机辅助设计(TCAD)模拟来探究侧向耗尽型氧化镓MOSFET设备在SEB中的敏感区域和安全操作电压&#xff0c;并提出了辐射损伤…

俊杰测评:电视盒子什么牌子好?电视盒子品牌排行榜

欢迎各位来到俊杰的数码测评频道&#xff0c;每年我会进行数十次电视盒子测评&#xff0c;今年已经买过二十多款电视盒子了&#xff0c;本期的测评主题是电视盒子什么牌子好&#xff0c;通过十天的深入详细对比后我整理了电视盒子品牌排行榜&#xff0c;近期想买电视盒子的可以…

C++运算符

运算符 作用&#xff1a;用于执行代码的运算 本文章主要讲解以下四种运算符&#xff1a; 1.算术运算符 作用&#xff1a;用于处理四则运算 算术运算符包括以下这些符号&#xff1a; 举例&#xff1a; 注&#xff1a; 在除法运算中&#xff0c;除数不能为0 在取模运算…

【MATLAB源码-第194期】基于matlab的MB-OFDM仿真,超宽带(UWB)无线传输。对比LS/DFT及其改进算法。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 一、无线通信的基本原理 无线通信是通过空气或其他介质传播电磁波来传输信息的技术。这种通信方式的核心在于电磁波&#xff0c;它能够在没有物理连接的情况下传输数据。无线通信的基本流程包括&#xff1a; 信号的生成&am…

Redis集合[持续更新]

Redis&#xff08;全称&#xff1a;Remote Dictionary Server 远程字典服务&#xff09;是一个开源的使用 ANSI C 语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库&#xff0c;并提供多种语言的 API。 数据结构 1. string 字符串 字符串类型是 Redis 最…

springboot实现SSE之牛刀小试

文章目录 一&#xff0c;概述1.SSE是何方神圣&#xff1f;2.sse与webscoket区别 二&#xff0c;实现过程1.效果展示2. 简要流程3. 源码放送4.完整项目 一&#xff0c;概述 1.SSE是何方神圣&#xff1f; SSE 全称Server Sent Event&#xff0c;直译一下就是服务器发送事件。 …

FPGA中闪灯程序设计示例

在FPGA设计中&#xff0c;闪灯的作用主要是用于测试和验证设计的功能和性能。具体来说&#xff0c;闪灯可以作为一个可视化的指示器&#xff0c;通过控制LED灯的闪烁模式和频率&#xff0c;来显示FPGA的工作状态或调试信息。 例如&#xff0c;在设计过程中&#xff0c;可以编写…

channel_shuffle代码实现

结构图&#xff0c;先将输入的图像进行通道拆分为组GConv1&#xff0c;每个GConv1再拆分Feature&#xff0c;每个GConv1的Feature进行合并GConv2&#xff0c;输出Output 输入图像x&#xff0c;拆分为groups个组&#xff0c;每隔组的通道数为channels_per_group batch_size, n…

binary tree Leetcode 二叉树算法题

144.二叉树的前序遍历 前序遍历是&#xff1a;根-左-右 所以记录序列的的时候放在最前面 递归 class Solution {List<Integer> ans new ArrayList<>();public List<Integer> preorderTraversal(TreeNode root) {if(root null) return ans;ans.add(root…