内容概要
双指针(Two Pointers):指的是在遍历元素的过程中,不是使用单个指针进行访问,而是使用两个指针进行访问,从而达到相应的目的。如果两个指针方向相反,则称为「对撞时针」。如果两个指针方向相同,则称为「快慢指针」。如果两个指针分别属于不同的数组 / 链表,则称为「分离双指针」。
滑动窗口(Sliding Window):在给定数组 / 字符串上维护一个固定长度或不定长度的窗口。可以对窗口进行滑动操作、缩放操作,以及维护最优解操作。滑动操作——窗口可按照一定方向进行移动。最常见的是向右侧移动。缩放操作——对于不定长度的窗口,可以从左侧缩小窗口长度,也可以从右侧增大窗口长度。
滑动窗口利用了双指针中的快慢指针技巧,我们可以将滑动窗口看做是快慢指针两个指针中间的区间,也可以可以将滑动窗口看做是快慢指针的一种特殊形式。
刷题
-
- 移动零
class Solution:
def moveZeroes(self, nums: List[int]) -> None:
left = 0
right = 0
while right < len(nums):
if nums[right] != 0:
nums[left],nums[right] = nums[right],nums[left]
left += 1
right += 1
-
- 颜⾊分类
对数组 nums 里面的每一个值 nums[i] 进行遍历,如果 nums[i] == 0 就放到前面,如果 nums[i] == 2 就放到后面,顺序就排好了。具体的操作中可以用两个指针 p0 和 p2 分别来标识 0 的下一位和2的上一位,p0 从0开始往后,p2 从 n-1 开始往前。
- 颜⾊分类
class Solution:
def sortColors(self, nums: List[int]) -> None:
left = 0
right = len(nums)-1
i = 0
while i <= right:
#nums[i] 和 nums[p2] 交换,nums[p2] 还没有被check过,交换后,nums[p2] 被交换到 nums[i] 的位置后,如果 i 移动到 i+1, 那么 nums[p2] 就被漏掉了。所以,要继续比较 nums[i] 是否等于 0 或 2。
while nums[i] == 2 and i <= right:
nums[i],nums[right] = nums[right],nums[i]
right -= 1
if nums[i] == 0:
nums[i],nums[left] = nums[left],nums[i]
left += 1
i += 1
return nums
-
- 合并两个有序数组
class Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
"""
Do not return anything, modify nums1 in-place instead.
"""
#l为nums1的m开始索引, r为nums2的n开始索引,index为修改nums1的开始索引,然后从nums1末尾开始往前遍历
l, r, index = m - 1, n - 1, len(nums1) - 1
#按从大到小,从后往前修改nums1的值,每次都赋值为nums1和nums2的当前索引的较大值,然后移动索引
while l >= 0 and r >= 0:
#如果nums1[l] >= nums2[r],则先赋值为nums1[l],l索引减少
if nums1[l] >= nums2[r]:
nums1[index] = nums1[l]
l -= 1
else:
#如果nums1[l] <= nums2[r],则先赋值为nums2[r],r索引减少
nums1[index] = nums2[r]
r -= 1
#当前nums1修改索引减少1
index -= 1
#nums2没有遍历完n个,则继续遍历,直到n个完成
while r >= 0:
nums1[index] = nums2[r]
r -= 1
index -= 1
-
- 反转字符串
class Solution:
def reverseString(self, s: List[str]) -> None:
n = len(s)
for i in range(n//2):
s[i], s[n-1-i] = s[n-1-i], s[i]
-
- 三数之和
class Solution:
def threeSum(self, nums: [int]) -> [[int]]:
nums.sort()
res, k = [], 0
for k in range(len(nums) - 2):
if nums[k] > 0: break # 1. because of j > i > k.
if k > 0 and nums[k] == nums[k - 1]: continue # 2. skip the same `nums[k]`.
i, j = k + 1, len(nums) - 1
while i < j: # 3. double pointer
s = nums[k] + nums[i] + nums[j]
if s < 0:
i += 1
while i < j and nums[i] == nums[i - 1]: i += 1
elif s > 0:
j -= 1
while i < j and nums[j] == nums[j + 1]: j -= 1
else:
res.append([nums[k], nums[i], nums[j]])
i += 1
j -= 1
while i < j and nums[i] == nums[i - 1]: i += 1
while i < j and nums[j] == nums[j + 1]: j -= 1
return res
-
- 删除有序数组中的重复项 II
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
if len(nums)<=2:
return len(nums)
lens=0
for n in nums:
if lens<2 or n>nums[lens-2]:
nums[lens]=n
lens=lens+1
return lens
-
- 最⻓连续递增序列
class Solution:
def findLengthOfLCIS(self, nums: List[int]) -> int:
size = len(nums)
if size == 0:
return 0
res = 1
#记录最长连续递增子序列长度
count = 1
#计算当前子序列的递增长度
for i in range(size - 1):
if nums[i + 1] > nums[i]:
count += 1
else:
count = 1
if count > res:
res = count
return res
-
- 最⼤连续1的个数 III
class Solution:
def longestOnes(self, nums: List[int], k: int) -> int:
res = cnt = l = r = 0
#缩小窗:包含0超过k时,开始缩小窗使其包含的0不超过k个
#cnt记录当前包含0的个数
while r<len(nums):
if nums[r] == 0:cnt+=1
#记录已经包含0的个数
r += 1
#扩大窗:包含0不超k时,不断右移扩大窗
while cnt > k:
if nums[l] == 0:cnt-=1
l += 1
res = max(res,r-l)
#更新结果
return res
-
- 存在重复元素 III
class Solution:
def containsNearbyAlmostDuplicate(self, nums: List[int], k: int, t: int) -> bool:
bucket_dict = dict()
for i in range(len(nums)):
# 将 nums[i] 划分到大小为 t + 1 的不同桶中
num = nums[i] // (t + 1)
# 桶中已经有元素了
if num in bucket_dict:
return True
# 把 nums[i] 放入桶中
bucket_dict[num] = nums[i]
# 判断左侧桶是否满足条件
if (num - 1) in bucket_dict and abs(bucket_dict[num - 1] - nums[i]) <= t:
return True
# 判断右侧桶是否满足条件
if (num + 1) in bucket_dict and abs(bucket_dict[num + 1] - nums[i]) <= t:
return True
# 将 i-k 之前的旧桶清除,因为之前的桶已经不满足条件了
if i >= k:
bucket_dict.pop(nums[i-k] // (t + 1))
return False
参考资料
https://github.com/itcharge
https://leetcode-cn.com/problems/sort-colors/solution/75-yan-se-fen-lei-python-shuang-zhi-zhen-pl1a/
https://leetcode-cn.com/problems/merge-sorted-array/solution/python3-shuang-zhi-zhen-xiu-gai-0mnfu-za-dee5/
https://leetcode-cn.com/problems/3sum/solution/3sumpai-xu-shuang-zhi-zhen-yi-dong-by-jyd/
https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array-ii/solution/xiao-bai-gan-wu-fen-xiang-by-zut_liu-kan-mxgn/