什么是双指针(Two Pointers)?
双指针是一种使用两个指针在数组或字符串上协同移动的算法技巧,常用于数组查找、子区间处理、排序归并、原地修改等场景。
我们可以把双指针想象成两个扫雷兵,一左一右,灵活分工协作: 有时一起向右推进,有时一个从左一个从右,甚至有时从中间出发各走各的。
双指针的使用根据指针的方向、数据结构、问题目标的不同,可以分为以下几种典型类型:
1. 相向双指针(Opposite Direction)
特点:
- 两个指针分别从数组或字符串的两端出发,向中间靠拢
- 用于有序结构的查找、回文判断、最大值判定等
适用场景:
- 判断是否为回文
- 寻找两个数满足某种和(如:two sum)
- 容器类极值问题(如:接水最多)
举例:你和朋友在清理一排杂乱的书架,你从左边开始拿书整理,朋友从右边开始放回原位,你们边清理边往中间靠近,直到书架整齐。
对应题目:
- 11. Container With Most Water
- 125. Valid Palindrome
- 167. Two Sum II - Input array is sorted
- 344. Reverse String
2. 同向双指针(Sliding Window)
特点:
- 两个指针一起从左向右推进,动态维护一个区间(窗口)
- 通常用于子数组、子字符串等局部范围统计问题
适用场景:
- 统计区间满足条件的子数组
- 无重复子串/最小覆盖串
- 求最大/最短区间长度
举例:你在逛菜市场,一个朋友推着车慢慢走,另一个拿着篮子挑菜,车子每走一段就统计篮子里菜的种类和重量,直到挑到最合适的组合。
对应题目:
- 3. Longest Substring Without Repeating Characters
- 76. Minimum Window Substring
- 209. Minimum Size Subarray Sum
- 713. Subarray Product Less Than K
3. 背向双指针(Center Expansion)
特点:
- 两个指针从同一个位置出发,分别向左右移动,向外扩展
- 常用于对称结构、从中心扩展的题型
适用场景:
- 找最长回文子串
- 以某个点为中心扩展的最大区间
举例:你站在桥中央,左右各派一个朋友沿桥两侧散步,边走边观察水面倒影,直到找到最对称的风景点。
对应题目:
4. 原地修改型双指针(In-Place Modification)
特点:
- 一个指针扫描原数组,一个指针处理结果区(快慢指针)
- 常用于原地移除元素、去重、数组重新排列
适用场景:
- 移除重复项、特定元素
- 将零移到末尾
- 原地排序
举例:你在厨房洗盘子,一个朋友在旁边擦干并归位,脏盘子被迅速清理,干净盘子被整齐摆放。
对应题目:
5. 双序列双指针(Two Sequences Alignment)
特点:
- 两个指针分别遍历两个数组/字符串,进行对齐、匹配或合并
- 适用于两个序列的同步操作
适用场景:
- 合并两个有序数组
- 查找交集或差异
- 长按键入等变形问题
举例:你和朋友一人拿着一份购物清单,对照着检查库存,一人从头读,一人从另一份清单核对,直到找到相同的商品。
对应题目:
6. 判断子序列(Is Subsequence)
特点:
- 判断一个序列是否为另一个序列的子序列
- 核心在于顺序匹配
适用场景:
- 判断能否通过跳过字符匹配成功
- 字符串匹配变体题
举例:你在看一本长篇小说,试图用另一本小书的片段“跳着读”验证它是否是长篇的子集。
对应题目:
- 392. Is Subsequence
- 524. Longest Word in Dictionary through Deleting
- 2486. Append Characters to String to Make Subsequence
7. 三指针及以上(Three or More Pointers)
特点:
- 通常用于组合枚举(如三数之和、四数之和)
- 多个指针配合跳过重复、剪枝搜索
适用场景:
- 三元组、四元组求和
- 稀疏数组对齐、子数组计数等
举例:三位厨师合作调配菜谱,每人负责一种配料,从冰箱里挑出组合,直到找到最美味的三味搭配。
对应题目:
📌 总结一句话:
双指针是解决数组和字符串「子结构」、「多序列同步」、「顺序筛选」、「滑动区间」等问题的高效利器,每一种指针策略都对应一类经典问题与模板技巧。