LeetCode 热题 100 题解(二):双指针部分(2)| 滑动窗口部分(1)

题目四:接雨水(No. 43)

题目链接:https://leetcode.cn/problems/trapping-rain-water/description/?envType=study-plan-v2&envId=top-100-liked

难度:困难


给定 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

提示:

  • n == height.length
  • 1 <= n <= 2 * 104
  • 0 <= height[i] <= 105

题解

首先来观察对于一个格子来说,它的容量是多少:

在这里插入图片描述

比如上图中的红色部分,它存储水的容量其实就是 左边的最大高度右边的最大高度 的 最小值,减去这里的格子高度(案例中为 0),在上面的案例中,左边的最高高度为 2,右边的最高高度为 3。

所以本题的暴力解法就比较好想了,找到其左边最大高度,再找到其右边的最大高度,通过上面的规律进行运算。

class Solution {public int trap(int[] height) {int res = 0;for (int i = 1; i < height.length; i++) {int left = i - 1;int right = i + 1;int maxLeft = 0;int maxRight = 0;while (left >= 0) { // 去左边寻找最大的maxLeft = Math.max(maxLeft, height[left--]);}while (right < height.length) { // 去右边寻找最大的maxRight = Math.max(maxRight, height[right++]);}int temp = Math.min(maxLeft, maxRight) - height[i]; // 执行运算逻辑res += temp > 0 ? temp : 0;}return res;}
}

这个方法的时间复杂度无疑是非常高的,因为每遍历到一个节点的时候都需要遍历整张表,接下来考虑如何对上面的方法进行优化。

首先来看左边的最大值,考虑一下,我们真的有必要每次去遍历来求得最大值吗?

可以将之前遍历过的节点的最大值保存下来,比如说这么一个高度数组 4,2,0,3,2,5 ,我们从第二个数字开始遍历,当执行完这个数字的逻辑之后,就可以拿它和之前的最大高度作比较,用作下一个节点的左边最大高度,这样不断更新就能保证每次求得的都是准确的。

class Solution {public int trap(int[] height) {int res = 0;int maxLeft = height[0];for (int i = 1; i < height.length; i++) {int left = i - 1;int right = i + 1;int maxRight = 0;while (right < height.length) { // 找到右边最大高度maxRight = Math.max(maxRight, height[right++]);}int temp = Math.min(maxLeft, maxRight) - height[i];res += temp > 0 ? temp : 0;maxLeft = Math.max(height[i], maxLeft); // 维护一个更新的 maxLeft}return res;}
}

既然对左边可以进行优化,那对右边是否可以优化呢?

因为是从前向后遍历的,所以右边肯定不可能像左边这样简单的更新;所以可以考虑提前处理,如果从后向前遍历的话,就可以类似左边那样求出 每个节点 的右最大值,所以可以在进入循环之前,先遍历一次高度数组,求出一个存储着每个节点右最大值的数组。

class Solution {public int trap(int[] height) {int res = 0;int maxLeft = height[0];int k = 2;int[] maxRight = new int[height.length];int m = height[maxRight.length - 1];for (int j = maxRight.length - 2; j >= 0; j--) { // 从后向前遍历,维护一个存储每个节点最大值的数组maxRight[j] = m;m = Math.max(m, height[j]);}for (int i = 1; i < height.length; i++) {int temp = Math.min(maxLeft, maxRight[i]) - height[i]; // 使用数组中的值res += temp > 0 ? temp : 0;maxLeft = Math.max(height[i], maxLeft);}return res;}
}

题目一:无重复字符的最长字串(No. 3)

题目链接:https://leetcode.cn/problems/longest-substring-without-repeating-characters/description/?envType=study-plan-v2&envId=top-100-liked

题目难度:中等


给定一个字符串 s ,请你找出其中不含有重复字符的 最长

子串

的长度。

示例 1:

输入:s = "abcabcbb"
输出:3
解释: 因为无重复字符的最长子串是"abc",所以其长度为 3。

示例 2:

输入:s = "bbbbb"
输出:1
解释:因为无重复字符的最长子串是"b",所以其长度为 1。

示例 3:

输入:s = "pwwkew"
输出:3
解释:因为无重复字符的最长子串是"wke",所以其长度为 3。请注意,你的答案必须是子串的长度,"pwke" 是一个子序列,不是子串。

提示:

  • 0 <= s.length <= 5 * 104
  • s 由英文字母、数字、符号和空格组成

题解

首先来看第一种方法,提到最长子串,想到的第一个方法就是动态规划。

先来尝试找一下状态,题目中问的是没有重复字符的最长的子串,可以将某个节点的状态定义为:以这个节点为结尾的,不含有重复字符的字串的最大长度,这种方式在处理子串的问题中非常常见。

再来思考这个状态应该如何转移。对于一个节点其实有这些选择

  • 从这个节点开始(重新开始)
  • 接续前面的子串

本题接续前面子串的时候要考虑不能含有重复的元素,所以并不像之前的题目那样就简单的做一个加一,但总而言之状态是可以转移的,那就来尝试一下。

先来确定 dp 数组,根据上面的推理,dp 数组只需要一维就即可, dp[i] 的含义为以 s.charAt(i) 为结尾的,不含有重复子串的最大长度。

然后就是确定状态转移方程了,对于一个下标为 x 的节点,它所代表的子串就是从 x - dp[i] 到 x 这个范围内内容;比如我们现在遍历到了下标为 x + 1 的节点,如果想要接续上前面的内容,就需要上面的范围中不含有 s.charAt(x + 1) 这个字符,此时需要通过遍历来确定是否有这个字符。

如果没有发现,那 dp[i] = dp[i - 1] + 1

如果发现了重复的字符串,比如下面的情况

在这里插入图片描述

此时要求得的是绿色的 b 的值,前一个节点最大子串的长度为 3,但当遍历到图中粉色的节点的时候发现了重复,此时 b 的长度应该为多少呢?是 2
画个图来更直观的了解一下:

在这里插入图片描述

当发现了相同的节点之后,这个值应该就是从被发现的位置索引 + 1 一直到新节点的长度

此时就确定了两种情况的递推公式,下面来讨论一下初始化

因为需要前一个节点的情况,所以 dp[0] 是要被初始化的,按照上面的含义,该位置应该被初始化为 1。

class Solution {public int lengthOfLongestSubstring(String s) {if (s.length() == 0) return 0;int[] dp = new int[s.length()];dp[0] = 1;int res = 1;for (int i = 1; i < s.length(); i++) {int field = dp[i - 1]; // 需要查询重复的范围char c = s.charAt(i);boolean findSame = false; // 是否找到了相同的节点while (field > 0) {int index = i - (field--);if (s.charAt(index) == c) { // 找到了相同的节点int m = i - index - 1 + 1;dp[i] = m;findSame = true;break;}}if (!findSame) dp[i] = dp[i - 1] + 1;res = Math.max(dp[i], res); // 动态更新 res}return res;}
}

接下来来看一下滑动窗口方案

所谓的滑动窗口其实就是用索引去限定一个范围,通过不断移动左范围和右范围的方式来调整窗口的范围,从而收集信息。

当滑动窗口的内容满足要求的时候就不断 移动右边界,来扩展滑动窗口的大小,如果发现不满足要求,也就是出现了重复的情况,就通过 收缩左边界 最终使得窗口内的元素始终满足要求,然后记录滑动窗口的长度。

滑动窗口方法的核心和上面的动态规划方法相同,都是通过遍历每个元素为 右节点 的情况,来不断更新最大值。

class Solution {char[] charArray;public int lengthOfLongestSubstring(String s) {if (s.length() == 0) return 0;charArray = s.toCharArray();int left = 0, right; // 左范围,右范围int res = 1;for (int i = 1; i < charArray.length; i++) {right = i;while (examine(left, right, charArray[i])) {left++;}res = Math.max(right - left + 1, res); // 更新结果}return res;}// 检测范围内是否有和此时右范围相同的元素public boolean examine(int left, int right, char c) {for (int i = left; i <= right - 1; i++) {if (charArray[i] == c) return true;}return false;}
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

树的总结学习

一、树的遍历 其实深度优先遍历&#xff1a;是指先序、中序和后序&#xff0c;广度优先就是层序遍历。 ①、先序遍历 void PreOrder(BTNode *b) {if(b ! NULL){std::cout << b->data << std::endl;PreOrder(b->left);PreOrder(b->right);} } ②、中序…

如何将三方库集成到hap包中——通过IDE集成非cmake方式构建的C/C++三方库

简介 DevEco Studio(简称IDE)目前只支持cmake构建方式&#xff0c;对于非cmake构建方式的三方库需要通过IDE工具集成的话&#xff0c;我们需要对原生库编写一个cmake的构建脚本。本文通过tinyxpath三方库为例介绍如何在IDE上移植一个非cmake构建方式的三方库。 cmake构建脚本…

中拔出溜的公司如何实施DEVOPS

虽然推进起来很艰难&#xff0c;但在这类公司也并非一无是处&#xff1a;只要让各方尤其是领导曾看到了成效&#xff0c;大范围铺开很容易&#xff0c;你也非常容易因此变得出众。 0. 标题 1. 中拔出溜公司的特点2. 循序渐进2.1 从研发团队开始2.2 先CI&#xff08;持续集成&am…

2024年第十七届“认证杯”数学中国数学建模网络挑战赛D题思路

D题 AI绘画带来的挑战(本题仅限专科组和爱好者组选用) 2023 年开年, ChatGPT作为一款聊天型AI工具,成为了超越疫情的热门词条;而在 AI 的另一个分支——绘图领域,一款名为 Midjourney(MJ)的软件,热度完全不亚于ChatGPT。AI绘画技术可以模仿设计师的风格和技巧,自动生…

中介者模式:简化对象间通信的协调者

在面向对象的软件开发中&#xff0c;中介者模式是一种重要的行为型设计模式&#xff0c;用于降低多个对象间通信的复杂性。通过提供一个中心化的对象来处理不同组件之间的交互&#xff0c;中介者模式使得组件间不必显式引用彼此&#xff0c;从而使其松散耦合、更易于维护。本文…

【日常记录】【CSS】生成动态气泡小球

文章目录 1、分析2、实现 1、分析 核心有两点&#xff0c;通过这两个不一样就可以实现每个小球的颜色、动画时间不一致 给每个元素都设置一个css 变量 bgc 用于控制每一个小球的颜色给每个元素都设置一个css 变量 duration 用于控制每一个小球的时间 2、实现 <!DOCTYPE ht…

Python连接星环数仓取数

有公众号群的小伙伴问我,有没有实现python连接星环数仓取数的代码,刚好有用,就做了一下分享。可能别的小伙伴也有需求,故分享到公众号中,感兴趣的小伙伴可以跟着实现一下。之前的文章分享了python连接sql取数和实现自动化发邮件代码,感兴趣的朋友可以到阿黎逸阳的代码公众…

STM32H7的Cache学习和应用

STM32H7的Cache学习和应用 啥是Cache&#xff1f;Cache的配置配置 Non-cacheable配置 Write through&#xff0c;read allocate&#xff0c;no write allocate配置 Write back&#xff0c;read allocate&#xff0c;no write allocate配置 Write back&#xff0c;read allocate…

在IntelliJIDEA中如何将依赖包打入项目中?

在IntelliJIDEA中将依赖包打入项目主要有以下几种场景和步骤&#xff1a; 一. 对于 Maven 项目&#xff1a; 在 pom.xml 文件中正确声明所需的依赖。IDEA 会自动从 Maven 仓库下载这些依赖。 构建项目时&#xff0c;默认情况下 Maven 不会将依赖包直接打进 JAR/WAR 文件中&am…

科软24炸穿了,25还能冲吗?

25考研&#xff0c;科软必然保持大热 不是吧兄弟&#xff0c;明眼人都能看出来&#xff0c;科软以后不会出现大冷的局面了&#xff0c;除非考计算机的人减少&#xff0c;因为科软简直是叠满了buff&#xff0c;首先科软的专业课是22408&#xff0c;考的是数学二&#xff0c;这就…

北斗导航 | 北斗三号区域短报文服务解析

===================================================== github:https://github.com/MichaelBeechan CSDN:https://blog.csdn.net/u011344545 ===================================================== 北斗三号区域短报文服务解析 1、引言2、北斗三号区域短报文服务原理与改…

腾讯云人脸服务开通详解:快速部署,畅享智能体验

请注意&#xff0c;在使用人脸识别服务时&#xff0c;需要确保遵守相关的法律法规和政策规定&#xff0c;保护用户的合法权益&#xff0c;并依法收集、使用、存储用户信息。此外&#xff0c;腾讯云每个月会提供一定次数的人脸识别调用机会&#xff0c;对于一般的小系统登录来说…

C++类和对象(四)——类的实现、const、explicit、static

1. 日期类的实现&#xff08;包括前置和后置&#xff09; Date.h #pragma once #include<iostream> #include<assert.h> using namespace std;class Date { public:bool CheckInvalid() const;Date(int year 1, int month 1, int day 1);bool operator<(co…

7. Spring Boot 创建与使用

经过前面的六篇文章&#xff0c;Spring Framework的知识终于大致讲完了&#xff0c;但是Spring AOP还没提到&#xff0c;个人认为Spring AOP更适合放在Spring MVC之后再讲解&#xff0c;而讲解Spring MVC前先学习Spring Boot的目的也是为了在学习Spring MVC的时候直接使用Sprin…

【云原生篇】K8S部署全面指南

部署Kubernetes&#xff08;K8s&#xff09;有多种方式&#xff0c;可以根据组织的需求、基础设施和资源来选择最合适的部署方法。以下是一些主流的Kubernetes部署方式&#xff1a; 1. 手动部署 kubeadm&#xff1a;Kubernetes官方提供的工具&#xff0c;可以帮助你快速部署和…

C#中计算矩阵的逆可以使用数学库

在C#中计算矩阵的逆可以使用数学库&#xff0c;比如MathNet.Numerics。这个库提供了丰富的数学函数&#xff0c;包括线性代数运算。以下是一个使用MathNet.Numerics计算矩阵逆的简单示例&#xff1a; 首先&#xff0c;你需要安装MathNet.Numerics库。你可以通过NuGet包管理器来…

项目管理软件评测:选择合适软件是关键

在过去&#xff0c;中小企业项目管理沿用的是office全家桶&#xff0c;用到后面项目由简单变复杂&#xff0c;项目资源越来越庞大&#xff0c;项目成员越来越多&#xff0c;项目管理问题日益凸显。好用的项目管理软件是化解问题的好方法&#xff0c;好用的项目管理软件是什么样…

蓝桥杯22年第十三届省赛-选数异或|暴力、线性dp

题目链接 5.选数异或 - 蓝桥云课 (lanqiao.cn) 思路&#xff1a; 重要结论&#xff1a;a^bx可得a^xb 暴力做法&#xff1a; 每次遍历给定区间的元素&#xff0c;将出现的元素建一个表表示这个数在区间里出现过&#xff0c;同时查这个元素a的a^x是否在表里&#xff0c;出现…

uwsgi 配置

uwsgi 官方文档&#xff1a;Python/WSGI 应用快速入门 — uWSGI 2.0 文档 安装uwsgi: pip install uwsgi 在【项目】目录下&#xff0c;manage.py 同级目录创建&#xff1a; myweb_uwsgi.ini 文件 &#xff08;名字随便起&#xff09; myweb_uwsgi.ini 内容配置&#xff…

C语言中的编译和链接

系列文章目录 文章目录 ​编辑 系列文章目录 文章目录 前言 一、 翻译环境和运行环境 二、 翻译环境 2.1 编译 2.1.1 预处理 2.1.2 编译 2.1.2.1 词法分析 : 2.1.2.2 语法分析 2.1.2.3 语义分析 2.1.3 汇编 2.2 链接 三、运行环境 前言 在我们平常的写代码时&#xff0c;我们很…