双指针题型:怎么识别、怎么讲、怎么练
双指针适合处理“相对移动关系”比历史状态更重要的问题,特别是顺序、对称性、去重规则决定答案的场景。
覆盖题量
60+
推荐起手
先判断是同向双指针还是相向双指针。
高频误区
没有基于有序性证明,就随意移动错误的一边。
什么时候该想到这个模式
下手前的检查清单
真正适合面试表达的解题步骤
先定义两个指针各自代表什么,再考虑怎么移动。
用当前比较结果证明哪一侧可以被安全丢弃。
除非题意要求,否则一次只移动一侧。
重复值要在会造成重复答案的地方处理掉。
最后回看循环条件,避免漏掉最后一个有效组合。
常见变体
相向双指针
适合有序数组、容器面积、目标和等从两端逼近的问题。
快慢指针
适合环检测、原地过滤和链表遍历。
分区双指针
适合按条件或 pivot 进行分组和分区。
模板预览
# Opposite-direction pointers on a sorted array
left, right = 0, len(nums) - 1
while left < right:
if good(nums[left], nums[right]):
return answer
if should_move_left(nums[left], nums[right]):
left += 1
else:
right -= 1
# Fast/slow pointers
slow = 0
for fast in range(len(nums)):
if keep(nums[fast]):
nums[slow] = nums[fast]
slow += 1
更像真实刷题路径的推荐题单
这组题不是随机罗列,而是按“先建立识别感,再补关键变体,最后上强度”去排,适合真的拿来做一轮 pattern 复习。
入门建立直觉
#1 Two Sum
找出两个数之和等于目标值的下标。
本质上是在做补数查询:遍历到 x 时,只要问 target - x 之前是否出现过。
入门建立直觉
#11 Container With Most Water
在若干条竖线中找出能装最多水的两条。
移动高的一侧没有意义,因为宽度变小,而短板仍然限制高度。
变体补齐关键状态
#15 3Sum
返回所有和为 0 的不重复三元组。
数组有序后,剩余两个数的移动方向完全由当前和偏小还是偏大决定。
变体补齐关键状态
#31 Next Permutation
把数组原地变成字典序更大的下一个排列。
pivot 右侧后缀天然是降序,这也是为什么我们能高效找到下一个更大元素并通过反转得到最小更大排列。
高频难点压强练习
#54 Spiral Matrix
按顺时针螺旋顺序返回矩阵中的元素。
每走完一条边后,都必须立刻收紧对应边界,否则元素就会被重复访问或漏掉。
高频难点压强练习
#146 LRU Cache
设计支持 O(1) get / put 的 LRU 缓存。
链表负责维护最近使用顺序,哈希表负责 O(1) 找到需要移动的节点。
高频坑点
没有基于有序性证明,就随意移动错误的一边。
在 3Sum 这类题里忘记跳过重复元素。
明明哈希更自然,却硬套双指针。
漏掉相等元素和指针相遇时的边界情况。
练习顺序建议
先刷 Two Sum II 和盛最多水的容器。
再做 3Sum 以及重度去重的数组题。
然后补链表里的快慢指针题。
最后再做更复杂的分区和环检测混合题。