- 同向双指针(快慢指针)
- 双向双指针(对撞指针)
- 滑动窗口
1. 同向双指针
初始时两指针同时指向头部,然后一前一后往数组后面进行遍历,不需要要求数组有序,本质上还是数组的查找。应用双向指针的场景:
- 要求对原数组进行变动
- 对原数组中的不满足条件的元素进行变动(后移、覆盖等)
283. 移动零 27. 移除元素 26. 删除有序数组中的重复项
1.1 典例讲解
1.1.1 移动零
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
示例:输入:【0,1,0,3,12】 输出:【1,3,12,0,0】说明:必须在原数组上操作,不能拷贝额外的数组。 尽量减少操作次数
难点:怎么对元素组进行边删除边做元素删除(后移)操作
解法:
1. 倒序遍历(for i in range(len(nums)-1, -1, -1))
2. 双指针(如何实现元素移动?)
解法1代码:
解法2代码:
注:上面两种代码,也都可以用while循环来实现
1.1.2 移除元素
给你一个数组 nums和一个值 val,你需要 原地 移除所有数值等于val的元素,并返回移除后数组的新长度。不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
示例 1:输入:nums = [3,2,2,3], val = 3输出:2, nums = [2,2] 示例 2:输入:nums = [0,1,2,2,3,0,4,2], val = 2输出:5, nums = [0,1,4,0,3]
同上一题
1.1.3 删除有序数组中的重复项
给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。
由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k 个元素,那么nums的前 k 个元素应该保存最终结果。将最终结果插入nums 的前 k 个位置后返回 k 。不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成
示例 1:输入:nums = [0,0,1,1,1,2,2,3,3,4]输出:5, nums = [0,1,2,3,4]
难点:双指针算法如何实现元素覆盖?
倒序的两种思路
双指针覆盖
2. 双向双指针
一般对有序数组, 两个指针一个指向头一个指向尾部, 然后两个指针同时向中间遍历,直到满足条件为止。
有序数组的平方 80. 删除有序数组中的重复项II 75. 颜色分类 977. 有序数组的平方
2.1 典例讲解
2.1.1 有序数组的平方
给定一个按非递减顺序排序的整数数组 A,返回每个数字的平方组成的新数组,要求也按非递减顺序排序。
示例 1: 输入:[-4,-1,0,3,10] 输出:[0,1,9,16,100] 示例 2: 输入:[-7,-3,2,3,11] 输出:[4,9,9,49,121]
先平方后排序
先排序后平方
提升:如何用双指针方法,在原数组上对元素按照绝对值进行排序?
2.1.2 删除有序数组中的重复项II 中等
给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 最多出现两次,返回删除后数组的新长度。不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
输入:nums = [0,0,1,1,1,2,3,3]输出:7, nums = [0,0,1,1,2,3,3]
难点:双指针删除时如何保留两个元素?
倒序解法
双指针
2.1.3 两数之和 II - 输入有序数组
给你一个下标从 1 开始的整数数组numbers ,该数组已按 非递减顺序排列 ,请你从数组中找出满足相加之和等于 目标数target 的两个数。
如果设这两个数分别是
numbers[index1]
和 numbers[index2]
,则 1 <= index1 < index2 <= numbers.length
以长度为 2 的整数数组 [index1, index2] 的形式返回这两个整数的下标 index1 和 index2。 你可以假设每个输入 只对应唯一的答案 ,而且你 不可以 重复使用相同的元素。空间复杂度O(1)在数组中找出两个元素,满足固定的条件(条件不随着查找的元素不同而变化)
1. 哈希表(保留遍历过的元素,往后寻找条件)
2. 双指针
3. 遍历查找(效率差)
哈希表
双指针
2.1.4 颜色分类 中等
给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻, 并按照红色、白色、蓝色顺序排列。此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色
必须在不使用库内置的 sort 函数的情况下解决这个问题。
示例 1: 输入:nums = [2,0,2,1,1,0] 输出:[0,0,1,1,2,2]
示例 2: 输入:nums = [2,0,1] 输出:[0,1,2]
1、复习下排序(冒泡、归并。。。)
2、双指针
双指针
计数(提供思路,并不是原地排序)
3. 滑动窗口
滑动窗口算法的基本思想是维护一个窗口,通过移动窗口的两个边界来处理问题。具体来说,我们可以使用两个指针left和right分别表示滑动窗口的左右边界,然后通过不断移动右指针right来扩大窗口,同时根据问题的要求调整左指针left来缩小窗口。在扩大或缩小窗口的过程中,可以记录下一些中间结果,例如最大值、最小值、子串长度等等,从而求解问题的最终答案。
滑动窗口算法的实现通常需要使用双指针技巧,通过不断移动指针来调整窗口的大小,并记录下中间结果。在扩大窗口时,右指针right不断向右移动,直到满足问题的要求;在缩小窗口时,左指针left不断向右移动,直到窗口中的序列不再符合要求。同时,每次移动指针前都需要更新一轮结果。
11. 盛最多水的容器 中等(双向指针)
给定一个含有n个正整数的数组和一个正整数 target 。找出该数组中满足其和 ≥ target 的长度最小的 连续子数组[numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
示例 1:输入:target = 7, nums = [2,3,1,2,4,3]输出:2 解释:子数组 [4,3] 是该条件下的长度最小的子数组。
示例 2:输入:target = 4, nums = [1,4,4]输出:1