当前位置: 首页 > news >正文

Day69:283. 移动零、11. 盛最多水的容器、42. 接雨水

283. 移动零

leetcode链接:https://leetcode.cn/problems/move-zeroes/

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。请注意 ,必须在不复制数组的情况下原地对数组进行操作。示例 1:输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]
示例 2:输入: nums = [0]
输出: [0]
提示:1 <= nums.length <= 104
-231 <= nums[i] <= 231 - 1
进阶:你能尽量减少完成的操作次数吗?

这题就是一个典型的快慢指针问题,类似于从数组中删除指定元素。快指针依次遍历,慢指针用来存放元素。思路就是先把所有的0元素删除,再在数组末位填充0,代码如下:

class Solution {
public:void moveZeroes(vector<int>& nums) {int slow = 0;for(int  i = 0 ; i < nums.size(); i++){if(nums[i] != 0){nums[slow++] =nums[i];}}//把剩下的位置填充为0for(int i = slow; i < nums.size(); i++){nums[i] = 0;}}
};

11.盛最多水的容器

给定一个长度为 n 的整数数组 height 。
有 n 条垂线,第 i 条线的两个端点是 (i, 0)(i, height[i]) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。返回容器可以储存的最大水量。说明:你不能倾斜容器。

这题是贪心算法,

  1. 接雨水

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。示例 1:输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 
示例 2:输入:height = [4,2,0,3,2,5]
输出:9

image

对于这种问题,我们不要想整体,而应该去想局部。仅仅对于位置 i,能装下多少水呢?

image

能装 2 格水,因为 height[i] 的高度为 0,而这里最多能盛 2 格水,2-0=2。

为什么位置 i 最多能盛 2 格水呢?因为,位置 i 能达到的水柱高度和其左边的最高柱子、右边的最高柱子有关,我们分别称这两个柱子高度为 l_maxr_max位置 i 最大的水柱高度就是 min(l_max, r_max)

也就是说:

water[i] = min(# 左边最高的柱子max(height[0..i]),  # 右边最高的柱子max(height[i..end]) ) - height[i]

根据该思路写一个暴力解法。

暴力解法

class Solution {
public:int trap(vector<int>& height) {int res = 0;for(int i = 1; i < height.size() - 1; i++){//这样才能保证左右都有柱子int leftMax= 0, rightMax = 0;for (int j = i; j < height.size(); j++)rightMax = max(rightMax, height[j]);// 找左边最高的柱子for (int j = i; j >= 0; j--)leftMax = max(leftMax, height[j]);cout<< leftMax << ',' << rightMax << endl;res += max(0, min(leftMax,rightMax) - height[i]);}return res;}
};

时间复杂度O(n2),实际上不需要每次都遍历,可以借助备忘录。

这里实际上res加的时候时候不需要和0比较,因为在计算 l_max 数组的时候是取「自己高度」和「目前左边最高」的最大值,因此 l_max[i] >= height[i] 是恒成立的。r_max 同理。

备忘录

不用每次都计算left和right,计算一次就好,存储在两个数组中:

class Solution {
public:int trap(vector<int>& height) {if (height.size() == 0) {return 0;}int res = 0;vector<int> leftMax(height.size(), 0);vector<int> rightMax(height.size(), 0);leftMax[0] = height[0];rightMax[height.size() - 1] = height[height.size() - 1];for(int i = 1; i < height.size() - 1; i++){//这样才能保证左右都有柱子leftMax[i] = max(height[i], leftMax[i - 1]);}for(int i = height.size() - 2; i >= 0; i--){rightMax[i] = max(height[i], rightMax[i + 1]);}for(int i = 1; i < height.size() - 1; i++){res += min(leftMax[i],rightMax[i]) - height[i];}return res;}
};

把时间复杂度降低为 O(N),已经是最优了,但是空间复杂度是 O(N)。双指针法可以把空间复杂度降到O(1)。

双指针法

之前不管是暴力解法还是备忘录,leftMax和rightMax分别代表 height[0..i]height[i..end] 的最高柱子高度:

image

而在双指针法中,代表的是 height[0..left]height[right..end] 的最高柱子高度:

image

我们只在乎 min(l_max, r_max)对于上图的情况,我们已经知道 l_max < r_max 了,至于这个 r_max 是不是右边最大的,不重要。重要的是 height[i] 能够装的水只和较低的 l_max 之差有关。

最终代码:

class Solution {
public:int trap(vector<int>& height) {int left = 0, right = height.size() - 1;int leftMax = 0, rightMax = 0;int res = 0;while (left < right) {leftMax = max(leftMax, height[left]);rightMax = max(rightMax, height[right]);// res += min(leftMax, rightMax) - height[i]if (leftMax < rightMax) {res += leftMax - height[left];left++;} else {res += rightMax - height[right];right--;}}return res;}
};

11. 盛最多水的容器

给定一个长度为 n 的整数数组 height 。有 n 条垂线,
第 i 条线的两个端点是 (i, 0)(i, height[i]) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。返回容器可以储存的最大水量。说明:你不能倾斜容器。

image

输入:[1,8,6,2,5,4,8,3,7] 输出:49 解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49

跟上面的题类似,直接贴代码:

class Solution {
public:int maxArea(vector<int>& height) {int res = 0;int left = 0, right = height.size() - 1;while(left < right){res = max(res, min(height[left], height[right]) * (right - left));if(height[left] < height[right]){left++;}else{right--;}}return res;}
};

这里要注意双指针的移动顺序,为什么是往height[i]小的那边移动?因为矩形的最大面积是由最短的那条边决定的:如果移动较低的那一边,那条边可能会变高,使得矩形的高度变大,进而就「有可能」使得矩形的面积变大;相反,如果你去移动较高的那一边,矩形的高度是无论如何都不会变大的,所以不可能使矩形的面积变得更大。

总结

感觉这样复习还是太零散没有体系了,从明天开始,还是按照模块来,先把原来的题二刷掉,然后再找拓展题。

相关文章:

Day69:283. 移动零、11. 盛最多水的容器、42. 接雨水

283. 移动零 leetcode链接&#xff1a;https://leetcode.cn/problems/move-zeroes/ 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。示例 1:…...

tensorrt的安装和使用

安装 提前安装好 CUDA 和 CUDNN&#xff0c;登录 NVIDIA 官方网站下载和主机 CUDA 版本适配的 TensorRT 压缩包即可。 以 CUDA 版本是 10.2 为例&#xff0c;选择适配 CUDA 10.2 的 tar 包&#xff0c;然后执行类似如下的命令安装并测试&#xff1a; #安装c版本 cd /the/pat…...

电压放大器在电子测试中的应用有哪些方面

电压放大器是一种常见的电子设备&#xff0c;广泛应用于各种测试和测量应用中。以下是电压放大器在电子测试中的几个主要方面应用的简要介绍。 信号采集与处理&#xff1a;电压放大器通常用于信号采集和处理&#xff0c;在测试过程中将低电平信号放大到适合进一步处理或分析的水…...

39.地址算术运算

如果p是一个指向数组中某个元素的指针&#xff0c;那么p将会对p进行自增运算并指向下一个元素&#xff0c;而pi将对p进行加i的增量运算&#xff0c;使其指向指针p当前所指向的元素之后的第i个元素。这类运算时指针或地址算术运算中最简单的形式。 allocbuf中的空间使用状况也是…...

没有外网的麒麟系统上搭建GitLab服务并且无需客户端账号密码验证

要在没有外网的麒麟系统上搭建GitLab服务并且无需客户端账号密码验证&#xff0c;可以按照以下步骤进行操作&#xff1a; 安装必要的依赖包和软件 sudo yum install curl policycoreutils-python openssh-server openssh-clients sudo systemctl enable sshd sudo systemctl …...

微服务生态系统:使用Spring Cloud构建分布式系统

文章目录 什么是微服务&#xff1f;为什么选择Spring Cloud&#xff1f;Spring Cloud的关键组件示例&#xff1a;构建一个简单的微服务步骤1&#xff1a;创建Spring Boot项目步骤2&#xff1a;配置Eureka服务发现步骤3&#xff1a;创建REST控制器步骤4&#xff1a;运行项目步骤…...

DIY 一个汽车方向盘游戏外设(MMOS OSW DIY)

OSW-MMOS直驱方向盘DIY过程记录 - 简书 (jianshu.com) DIY 一个汽车方向盘游戏外设&#xff08;MMOS OSW DIY&#xff09; 首先讲一下这个直驱系统大概的框架&#xff0c;首先是电脑&#xff0c;电脑里装MMOS的软件(这个软件国内高手把它汉化了的)&#xff0c;电脑通过USB线&a…...

校园网络技术需求分析

路由技术&#xff1a; 路由协议工作在 OSI 参考模型的第 3 层&#xff0c;因此它的作用主要是在通信 子网间路由数据包。路由器具有在网络中传递数据时选择最佳路径的能力。 除了可以完成主要的路由任务&#xff0c;利用访问控制列表&#xff08;Access Control List&#x…...

计算机网络(二):TCP篇

文章目录 1. TCP头部包含哪些内容&#xff1f;2. 为什么需要 TCP 协议&#xff1f; TCP 工作在哪一层&#xff1f;3. 什么是 TCP &#xff1f;4. 什么是 TCP 连接&#xff1f;5. 如何唯一确定一个 TCP 连接呢&#xff1f;6. UDP头部大小是多少&#xff1f;包含哪些内容&#xf…...

测试登录界面:Python

import unittest from selenium import webdriver class LoginTest(unittest.TestCase): def setUp(self): self.driver webdriver.Chrome() def test_login(self): # 打开登录页面 self.driver.get("http://example.com/login") # 输入用户名和密码 user…...

Rust踩雷笔记(7)——两个链表题例子初识裸指针

目录 leetcode 234leetcode 19 leetcode 234 题目在这https://leetcode.cn/problems/palindrome-linked-list/&#xff0c;leetcode 234的回文链表&#xff0c;思路很简单&#xff0c;就是fast和slow两个指针&#xff0c;fast一次移动两个、slow一次一个&#xff0c;最后slow指…...

用什么命令看Linux系统的体系架构

要查看Linux系统的体系架构&#xff0c;可以使用uname命令。在终端中运行以下命令&#xff1a; uname -m该命令将返回系统的体系架构&#xff0c;例如x86_64表示64位系统&#xff0c;i686表示32位系统。 uname 使用方法 uname命令用于获取操作系统的相关信息。它可以用于显示…...

消息中间件大揭秘:选择之前你必须知道的关键信息

Hello大家好&#xff01;我是小米&#xff0c;很高兴再次和大家见面&#xff01;今天的话题非常精彩&#xff0c;我们将深入探讨消息中间件&#xff0c;并了解一些常见的消息队列&#xff1a;RabbitMQ、RocketMQ、Kafka以及Redis。如果你正在准备面试&#xff0c;或者只是对这些…...

【Unity基础】4.动画Animation

【Unity基础】4.动画Animation 大家好&#xff0c;我是Lampard~~ 欢迎来到Unity基础系列博客&#xff0c;所学知识来自B站阿发老师~感谢 &#xff08;一&#xff09;Unity动画编辑器 &#xff08;1&#xff09;Animation组件 这一张我们要学习如何在unity编辑器中&…...

FreeRTOS移植以及核心功能

文章目录 freertos和ucos区别&#xff0c;优缺点比较移植步骤核心功能内存管理&#xff08;5种内存管理策略&#xff09;FreeRTOS任务调度算法有三种时间管理通信管理 栈管理 freertos和ucos区别&#xff0c;优缺点比较 FreeRTOS&#xff08;Free Real-Time Operating System&…...

重装系统(配置环境)

这里写目录标题 0.重装系统1.python1.1 anaconda1.2 pycharm1.3 深度学习环境配置 2.java2.1.安装JDK2.2.配置JDK环境变量2.3IDEA2.4 Maven 3.大数据3.1 虚拟机3.2 Hadoop平台3.3 存储3.4 采集3.5 计算3.6 查询3.7 可视化 0.重装系统 // An highlighted block var foo bar;1.…...

docker系列-报错以及解决指南

1. windows运行docker报错Windows Hypervisor is not presentDocker Desktop is unable to detect a Hypervisor.Hardware assisted virtualization and data execution protection must be enabled in the BIOS. Docker Desktop - Windows Hypervisor is not presentDocker D…...

Vue3快速上手

1.Vue3简介 2020年9月18日&#xff0c;Vue.js发布3.0版本&#xff0c;代号&#xff1a;One Piece&#xff08;海贼王&#xff09;耗时2年多、2600次提交、30个RFC、600次PR、99位贡献者github上的tags地址&#xff1a;Release v3.0.0 One Piece vuejs/core GitHub 2.Vue3带…...

二叉搜索树(BST,Binary Search Tree)

文章目录 1. 二叉搜索树1.1 二叉搜索树概念1.2 二叉搜索树的查找1.3 二叉搜索树的插入1.4 二叉搜索树的删除 2 二叉搜索树的实现3 二叉搜索树的应用3.1二叉搜索树的性能分析 1. 二叉搜索树 1.1 二叉搜索树概念 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&#xf…...

分析key原理

总结&#xff1a; key是虚拟dom对象的标识&#xff0c;当数据发生变化时&#xff0c;vue会根据新数据生成新的虚拟dom&#xff0c;随后vue进行新虚拟dom与旧虚拟dom的差异比较 比较规则&#xff1a; ①旧虚拟dom中找到了与新虚拟dom相同的key 若虚拟dom中的内容没变&#xff0c…...

docker详细操作--未完待续

docker介绍 docker官网: Docker&#xff1a;加速容器应用程序开发 harbor官网&#xff1a;Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台&#xff0c;用于将应用程序及其依赖项&#xff08;如库、运行时环…...

java 实现excel文件转pdf | 无水印 | 无限制

文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析

这门怎么题库答案不全啊日 来简单学一下子来 一、选择题&#xff08;可多选&#xff09; 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘&#xff1a;专注于发现数据中…...

前端导出带有合并单元格的列表

// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

基于Uniapp开发HarmonyOS 5.0旅游应用技术实践

一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架&#xff0c;支持"一次开发&#xff0c;多端部署"&#xff0c;可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务&#xff0c;为旅游应用带来&#xf…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

MySQL:分区的基本使用

目录 一、什么是分区二、有什么作用三、分类四、创建分区五、删除分区 一、什么是分区 MySQL 分区&#xff08;Partitioning&#xff09;是一种将单张表的数据逻辑上拆分成多个物理部分的技术。这些物理部分&#xff08;分区&#xff09;可以独立存储、管理和优化&#xff0c;…...

在 Spring Boot 项目里,MYSQL中json类型字段使用

前言&#xff1a; 因为程序特殊需求导致&#xff0c;需要mysql数据库存储json类型数据&#xff0c;因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...

大数据治理的常见方式

大数据治理的常见方式 大数据治理是确保数据质量、安全性和可用性的系统性方法&#xff0c;以下是几种常见的治理方式&#xff1a; 1. 数据质量管理 核心方法&#xff1a; 数据校验&#xff1a;建立数据校验规则&#xff08;格式、范围、一致性等&#xff09;数据清洗&…...