双指针算法是一种通过使用两个指针(索引或引用)在数据结构中有序移动来高效解决问题的技巧。它常用于数组、链表等线性结构的问题,能显著优化时间和空间复杂度。以下是其核心应用场景及使用方法:
核心应用场景
- 有序数组的两数之和
- 左右指针从两端向中间移动,根据当前和调整指针位置。
- 合并有序数组/链表
- 从后向前填充避免覆盖,或直接比较节点合并。
- 快慢指针检测链表环
- 快指针每次走两步,慢指针走一步,相遇则有环。
- 滑动窗口(子数组/子串问题)
- 维护窗口的左右边界,动态调整窗口大小以满足条件。
- 原地修改数组(去重、移除元素)
- 慢指针标记有效位置,快指针遍历寻找新元素。
通用实现步骤
- 初始化指针
- 根据问题类型设置左右指针初始位置(如头尾、同起点)。
- 确定移动条件
- 根据当前指针指向元素的关系或问题约束,决定如何移动指针。
- 终止条件
- 通常为指针越界(如左指针超过右指针)或达到目标状态。
经典代码示例
1. 有序数组的两数之和(左右指针)
python
def two_sum(nums, target):
left, right = 0, len(nums) - 1
while left < right:
current_sum = nums[left] + nums[right]
if current_sum == target:
return [left, right]
elif current_sum < target:
left += 1
else:
right -= 1
return []
2. 合并有序数组(逆向双指针)
python
def merge(nums1, m, nums2, n):
p1, p2, p = m-1, n-1, m+n-1
while p1 >= 0 and p2 >= 0:
if nums1[p1] > nums2[p2]:
nums1[p] = nums1[p1]
p1 -= 1
else:
nums1[p] = nums2[p2]
p2 -= 1
p -= 1
nums1[:p2+1] = nums2[:p2+1] # 处理剩余元素
3. 移除有序数组重复项(快慢指针)
python
def remove_duplicates(nums):
if not nums:
return 0
slow = 0
for fast in range(1, len(nums)):
if nums[fast] != nums[slow]:
slow += 1
nums[slow] = nums[fast]
return slow + 1
使用技巧
-
滑动窗口模板
pythonleft = 0 for right in range(len(nums)): # 更新窗口状态(如加入nums[right]) while 窗口不满足条件: # 更新窗口状态(如移除nums[left]) left += 1 # 记录结果(如最大/最小窗口长度)
-
链表问题
- 快慢指针找中点:快指针到末尾时,慢指针指向中点。
- 判断环:快慢指针相遇则有环,相遇后从头步进找到环入口。
适用问题特征
- 线性结构(数组、链表、字符串)。
- 需要高效遍历或比较连续元素。
- 暴力解法时间复杂度高(如O(n²)),双指针可优化到O(n)或O(n log n)。
通过合理选择指针移动策略,双指针能高效解决大量问题,是算法面试中的必备技巧。