概述:该模块主要用来记录第二个模块双指针,题目来源于Roadmap:https://neetcode.io/roadmap中的第二个模块。
双指针:
顾名思义双指针指的就是一次遍历中可以使用到两个指针同时处理一个字符串或者数组,这里的指针一般来说都是指数组下标。
EASY:这个难度的题目就是对双指针的表面意思的使用,这里的例题是判断字符串是否回文,就可以将储存好的字符串一个指针定义为i另一个则为n.size()-i然后判断这两个下标对应的字符串是否相等即可。这里只需要遍历左指针,结束条件为i<n.size()/2这样当长度为奇数时,最中间的数字就不需要理会。
题目:leetcode 125.Valid Palindrone
MEDIUM:中等难度主要给出了两种题型。第一种是选中数组中和为target两个/三个数并返回其下标,第二种是给出了n幢楼的高度,并求出能容纳水的最大含量。
先看第一种题 leetcode 167.Two Sum leetcode 15.3Sum
暴力的方法很简单,对于两个数求和就是两个for遍历数组,三个数求和就是三个for遍历,所以时间复杂度上来说分别是O(n^2)以及O(n^3),我们看输入范围:
这是Two Sum的输出长度3*10^4平方后是9*10^8接近10^9的时间复杂度(3Sum分析下来也是接近10^9的时间复杂度,写题经验来看的话(虽然我做的题不是那么多)10^9基本都是会爆的,所以我们考虑优化的算法。
优化:
从题目中说的排好序入手,其实这个条件可以直接看做他希望你用双指针。原因是由于序列顺序已知为升序,所以当我们求得两数和与目标值不相等时:1.和小于目标-移动左指针,使小的值变大从而使和接近目标值。2.和大于目标-移动右指针,使大的值变小,从而使和接近目标值。按照这个思路的双指针,就很容易解决问题了。
解法如下:
而针对三个数求和的问题也有很好的方法使得O(n^3)变成O(n^2)即为:遍历左指针来确定目标左区间的左界,增加一个指针mid和right用来遍历这个目标区间内的值(这两个新的指针充当Two Sum中的两个旧指针的作用)然后中间的mid和right指针同样如同Two Sum一样操作,方法如下:
只需要保证数组有序,多加一层for循环,思路就一样了。
楼间体积求和:
题目:leetcode 11.Container With Most Water
题目给出了长度为n的数组heights代表下标为i的建筑的高度为heights[i],问两栋楼间能围成的容器最大体积为多少。先用暴力:两层for遍历左右的可能性,并使用一个变量来记录出现的最大值,最后输出最大值即可。基本思路有了,但是看一眼样例范围:2-10^5明显是不让我们用O(n^2)的解决方案。这里用到一种贪心的思想:在相同的距离内,选择两个尽可能高的楼或者在相同高的两栋楼上选择距离尽可能远的两栋。基于这个思路写了一下代码:
不用考虑,到底是去贪心高度还是贪心距离,使用ans来记录最大的值,这样就可以保证不会因为选择了另一种情况而丢失了最优解。
HARD:题目给出了一个长度为n的数组其中nums[i]代表着下标为i的地方存在着一个高度为nums[i]的建筑,假设天上下雨,两个楼可以看做是水桶的侧壁,求出这个数组能装下多少容量的水。这道题没有使用传统的双指针模板,但是使用了双指针的思路,维护两个数组left和right,left[i]和right[i]分别代表了从0-i以及从i到n.size()中出现的最高的建筑物的高度,由于能接到水的容量大小取决于最矮的楼的高度所以有了一下思路:
这里维护数组的方式:num[i]为前i个数最大/最小的值是算法中常使用的一种记录方式。这边主要解释一下sum这行的逻辑:首先我们知道left[i]和right[i]代表着从左或者从右到下标i的最值,这里对两边的最大值取到最小值代表这是水桶的短边,决定了水桶容积的下限,然后从左向右遍历,假如当前点的楼层高度为1,并且求得两个最大值的最小值为2,代表着当前这个点可以存储2-1=1容积的水,并且该点的右边和左边边还会存在一个高度大于等于2的楼层围住这栋楼,形成一个桶,由于提前知道了某一点的左右信息,所以我们只需要每次处理当前点能储存的水的容积,即可解得这道题。
这里另外提到一个分析算法类竞赛时间复杂度的文件供自己学习——链接
该模块题目较少,能学到的东西较为有限,若有勘误,请联系我。