力扣100题-双指针
1.移动零
描述:给定一个数组
nums
,编写一个函数将所有0
移动到数组的末尾,同时保持非零元素的相对顺序。请注意 ,必须在不复制数组的情况下原地对数组进行操作。
思路一:
- 从左到右遍历数组,发现非零数就按序重写到原数组中,再在数组的后半截补全对应的0,实现了不构建新数组
- 代码:
1 |
|
思路二:
- 有点神似快排,交换的条件是当前的数是非零的。左指针左边均是非零数,右指针到左指针为止皆是0(一般情况)
- 代码:
1 |
|
2.盛最多水的容器
描述:给定一个长度为
n
的整数数组height
。有n
条垂线,第i
条线的两个端点是(i, 0)
和(i, height[i])
。找出其中的两条线,使得它们与
x
轴共同构成的容器可以容纳最多的水。返回容器可以储存的最大水量。
说明:你不能倾斜容器。
思路一:
- 贪心算法,左右指针分别从两端开始往中间靠,此时中间的任意的选择都是有可能。比较两个指针指向的数,选择高度较小的往中间走一步。
- ==证明==:从第一步开始假设,当前两个指针l, r直向左右两端,值分别是x, y,假设x<=y,距离为t,那么此时的结果就是min(x, y)*t = xt。假设左指针不动,此时右指针可以向左移动,不管怎么移动,其结果都是小于xt的,因为此时距离减少了,而min(x, y(new)) <= min(x, y) = x。因此所有以左指针为一端的结果都可以直接舍弃掉了,于是可以直接选择将左指针向右移动一步即可。
- 代码:
1 |
|
3.三数之和:
描述:给你一个整数数组
nums
,判断是否存在三元组[nums[i], nums[j], nums[k]]
满足i != j
、i != k
且j != k
,同时还满足nums[i] + nums[j] + nums[k] == 0
。请你返回所有和为0
且不重复的三元组。注意:答案中不可以包含重复的三元组。
思路一:
关键在于降低时间复杂度和重复的剪枝,暴力的做法就是三层循环O[N^3]。首先对数组进行排序,方便计算,在第二层和第三层循环使用双指针,不断向中间移动来寻找对应的target,这部分的时间复杂度就从O[N^2]降低到O[N]了。然后是在第一二层循环的时候都进行一下判重,找到并使用多个连续的重复数字的最后那一个。
代码:
1 |
|
4.接雨水:
- 描述:给定
n
个非负整数表示每个宽度为1
的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
思路一:
- 动态规划,提前维护数组LeftMax和RightMax,对于每一个位置来说,它能接收的与水量为左右两边对应的最大值取较小值然后减去当前位置的高度。相当于求每个位置上的雨水高度然后累加
- 代码:
1 |
|
思路二:
- 单调栈,维护一个递减的序列,当遇到一个大于当前栈顶的值时,就出栈一个为top,然后将此时的栈顶和当前的值作为两端,top作为计算的位置。是以矩阵形式累加答案的,通过遍历一边数组就合计了所有的计算,很巧妙。
- 代码:
1 |
|
思路三:
- 双指针,是对思路一的优化,对于每个点,只需要知道它左右的最大值分别是多少即可,不需要把所有的值都计算出来,而这个需要的值可以在双指针移动的过程中得到。
- 代码:
1 |
|
小节:
- 双指针对于数组的操作更加灵活,比如移动零,可以对元素进行划分,也类似快速排序里的双指针
- 双指针+排序可以降低时间复杂度,把O[N^2]降为O[N]
- 双指针也可以是两个数组的简化,比如接雨水,作为重要的临时变量,按具体情况进行移动
- 更多在于元素之间的关系的体现,通过移动来实现一种筛选
力扣100题-双指针
http://example.com/2024/08/04/力扣100题/力扣100题-双指针/