leetcode hot100_part02_双指针

devtools/2024/11/13 10:38:21/

283.移动零

. - 力扣(LeetCode);当前遍历位置不为0,左右指针一起前进,前进到为0的位置,左指针停下,右指针继续前进,右指针直到前进到第一个不为0的位置,然后交换,再一起前进;

11.盛水最多的容器

        偷看了一下评论区的小提示写出来的,头尾双指针往中间移动,怎么移动?用贪心,尽可能的往能够使面积更大的方向移动。最长递增子序列的第二个方法用的也是贪心。体会到了。能靠近就靠近一点。

        暂时还没看官方的解法,就是首尾往中间移,怎么移动?尽可能往面积大的朝向。

        往中间移长度肯定是减小,如果想面积S大肯定是要高度变高,S肯定是取决于高的那个,所以我们先找出两边中矮的那个,让它往中间移动,移动的结果肯定是要变高才有效,才有可能使面积变大,否则S肯定减小。

        想一想为什么一定要移动矮的,移动高的向中间靠近不行吗?(不行,分类讨论一下就行,移动高的,无论移动后高度变高还是变矮,s都变小)

        所以让两边里矮的移动,每移动一步判断是否变高,变高了就计算结果迭代比较;没有变高就继续移动。因为往里移动时只要矮的变高才有可能使S变大。

        官方的思路不够简洁,每次矮的只移动一个,可以直接让矮的往里移动到第一个比它大的位置。

9/12

        看了上面之前的思路,我觉得没啥要补充了;所以往更大的方向移动,双指针何尝不是一种贪心呢

15.三数之和

        视频讲的很通透:两数之和 三数之和【基础算法精讲 01】_哔哩哔哩_bilibili

        对于两数之和||,一个递增排好序的数组,找到两个不同下标的数使其和为target;l和r分别指向index = 0 和 len -1;如果当前和>target,r--;小于target, l++;关键是时间复杂度从O(n^2)降为O(n)

        三数之和就是遍历每个数,让它成为target;先排序后用上面同样的方法;时间复杂度O(n^2)

        注意三个数的下标不同,还有就是不能出现重复的结果(重复的三个数);代码写的时候发生了几个错误;想想三个下标的范围,还有就是相等情况下l++r--写成l++r++;你不越界谁越界

42.接雨水

还有接雨水II呢。

9/12

官方解法

代码参考:. - 力扣(LeetCode)

单调栈

        感觉很难想啊,把抽象的做法用易于理解的语言表述出来;. - 力扣(LeetCode)的解法5;

        我们用栈保存每堵墙(每个height[i]);当遍历墙的高度的时候,如果当前高度小于栈顶的墙高度,说明这里会有积水,我们将墙的高度的下标入栈。

        如果当前高度大于栈顶的墙的高度,说明之前的积水到这里停下,我们可以计算下有多少积水了。计算完,就把当前的墙继续入栈,作为新的积水的墙。

总体的原则:

  • 当前高度小于等于栈顶高度,入栈,指针后移。
  • 当前高度大于栈顶高度,出栈,计算出当前墙和栈顶的墙之间水的多少,然后计算当前的高度和新栈的高度的关系,重复第 2 步。直到当前墙的高度不大于栈顶高度或者栈空,然后把当前墙入栈,指针后移。

        关于每个坑位面积的叠加,是横着算的,因为对于i位置来说,我们当前的位置是i之后第一个比i大的,不细说了,不懂看灵山视频吧

前后缀

        在滑动窗口最大值的第三种解法,也是前后缀;回忆一下;

        我们用 leftMax[i] 表示下标 i 之前,包括下标 i 的数组元素最大值,rightMax[i]表示下标 i 之后包括下标 i 的数组元素最大值;为什么定义这两个数组呢?我们把每个位置 i 看做一个竖直方向的水桶;那么水桶的左右高度就是leftMax[i]和rightMax[i];单个水桶的宽为1,减去高度就是每个水桶的水;叠加就行;

双指针(前后缀优化)

        是前后缀的一个优化方案,这个方法中我们不需要再定义前后缀数组,而是用preMax和sufMax表示 l 和 r 指针走过的前缀和后缀的最大值(实时性)代替前后缀数组;

        l 和 r 分别初始化为数组元素的头和尾,想象一下数组的坑中没有水,然后下起了小雨,对于某个坑位 i 能接到的雨水最大值;

       如果当前 l 就在 i 位置,且preMax < sufMax;由于短板效应,l位置水桶能接多少雨水取决于preMax;为什么?虽然不知道 l + 1 位置的高度,但是 r 指针遍历到的当前的sufMax已经大于 l 的preMax;

        l~r 之间的柱子的高度h如果小于sufMax,那么l位置有sufMax这个右边的高度进行兜底(想象所有坑都接满的状态),h如果大于sufMax就更不用说了;

        所以当当前 l 就在 i 位置,且preMax < sufMax,我们就可以算出这个坑的雨水;同理当前r在 i 位置,且preMax > sufMax,我们也可以算出 r 位置的雨水量;并在这两种情况计算完后分别移动l , r;直至相遇遍历完所有的坑位;

4/14

双向遍历

        这个思路好像来源于之前,只记得那个最长括号匹配的题目了。首先想到的是计算每个可能接到雨水的坑。

        先从头开始遍历,fast比low领先一个位置,fast肯定要移动到大于等于low的位置才能接到雨水,当fast到了第一个比low大的位置时停下,在这个遍历期间记录了比low小的位置之和,求面积的时候减去,得到一个坑位的雨水量。然后low移动到fast的位置(折叠了起来),fast设置为其后的一个位置,继续求坑位的雨水量。

        那么,思考一下当fast为所有的坑里最高的那个,计算完之后对low,fast置,low为最高的,后面的坑不会再求了。因为我们设置的fast高度>=low高度时再求。

        所以正向遍历也就截止到最高处。这里特别注意最高处有等高的情况。

        那么我们进行反向遍历,low为最后一个位置,流程是一样的。得到最高处后面的坑位。如果最高处是等高的话,想一下,会重复计算的。因此我们反向遍历的时候,fast指针要截止到正向遍历时最高等高情况的最后一个位置tag。以防重复计算。

class Solution {public int trap(int[] height) {int reduce_mid = 0;int res = 0;// 从前往后,包含等高情况int low = 0;int fast = low + 1;int tag = 0;while (fast < height.length) {if (height[fast] < height[low]) {reduce_mid += height[fast];fast++;} else {// >=res = res + (fast - low - 1) * height[low] - reduce_mid;reduce_mid = 0;// 标记tag = fast;low = fast;fast = low + 1;}}// 从后往前,遇到等高情况跳过// 置零!!reduce_mid = 0; low = height.length - 1;fast = low - 1;while(fast >= tag ){if(height[fast] < height[low]){reduce_mid += height[fast];fast--;}   else {res = res + (low - fast - 1) * height[low] - reduce_mid;reduce_mid = 0;low = fast;fast = low - 1;}}return res;}
}

        


http://www.ppmy.cn/devtools/114533.html

相关文章

尚品汇-秒杀商品存入缓存、Redis发布订阅实现状态位(五十一)

目录&#xff1a; &#xff08;1&#xff09;秒杀业务分析 &#xff08;2&#xff09;搭建秒杀模块 &#xff08;3&#xff09;秒杀商品导入缓存 &#xff08;4&#xff09;redis发布与订阅实现 &#xff08;1&#xff09;秒杀业务分析 需求分析 所谓“秒杀”&#xff0…

计算机人工智能前沿进展-大语言模型方向-2024-09-13

计算机人工智能前沿进展-大语言模型方向-2024-09-13 1. OneEdit: A Neural-Symbolic Collaboratively Knowledge Editing System Authors: Ningyu Zhang, Zekun Xi, Yujie Luo, Peng Wang, Bozhong Tian, Yunzhi Yao, Jintian Zhang, Shumin Deng, Mengshu Sun, Lei Liang, Z…

【vue3】vue3.5

vue3.5是9.1发布的&#xff0c;还挺热乎的&#xff0c;赶快学习起来&#xff01;&#xff01;&#xff01; 组件属性结构解析赋值 组件属性结构解析赋值&#xff0c;高度提高开发体验&#xff0c;这个特性曾经在vue3.3提出过&#xff0c;然后3.4废弃&#xff0c;终于3.5稳定了。…

各种文件格式对应的ContentType,适用于文件接收与上传下载等场景...

Content-Type&#xff0c;即内容类型&#xff0c;是HTTP协议中的一个头部字段&#xff0c;用于指示发送到接收端&#xff08;通常是Web服务器或Web客户端&#xff0c;如浏览器&#xff09;的实体主体的媒体类型。它告诉浏览器或相关设备如何显示或处理加载的数据。Content-Type…

操作数组不越界的妙法C++

缘由https://bbs.csdn.net/topics/397090550 这个算法就不会越界&#xff0c;其关键在于-1之妙。string aa "123456789"; int a aa.size(), x 0;while (a)cout << aa[a-1] << endl,--a;while (x < a)cout << aa[x] << endl,x; void …

小明,谈谈你对Vue nextTick的理解

一、nextTick 的实现细节 在 Vue 中&#xff0c;nextTick 是一个重要的异步操作工具&#xff0c;用于在 DOM 更新完成后执行回调函数。其实现依赖于微任务机制&#xff0c;以确保操作在下一个“事件循环”中执行。以下是 nextTick 的具体实现过程&#xff1a; 任务队列&#xf…

神经网络 归一化层

为什么要进行网络归一化层&#xff1f; 神经网络训练过程中&#xff0c;当网络层数较多的时候&#xff0c;每一轮训练每个网络层的参数都会发生变化&#xff0c;那么网络层参数变化会有什么影响呢&#xff1f; 1. 向网络中输入相同分布的样本时&#xff0c;由于每一层网络的参…

自建数据库VS云数据库:从《中国数据库前世今生》看未来数据管理的抉择

自建数据库VS云数据库&#xff1a;从《中国数据库前世今生》看未来数据管理的抉择 在数字化时代的滚滚洪流中&#xff0c;数据库作为核心数据管理工具&#xff0c;始终扮演着至关重要的角色。最近观看了纪录片《中国数据库前世今生》&#xff0c;让我对数据库技术的发展有了更…