5. 双指针题怎么理解
双指针是手撕代码中非常实用的技巧,测试岗面试也经常出现。双指针并不是一种固定算法,而是一种思路:用两个指针协同移动,减少不必要的遍历。常见形式包括左右指针、快慢指针、同向双指针。它经常用于数组、字符串和链表题。
测试岗常考的双指针题包括:反转字符串、判断回文、移动零、合并有序数组、删除有序数组重复项、判断链表是否有环。掌握双指针,很多题都能写得简洁。
一、双指针有哪些类型
1. 左右指针
一个从左开始,一个从右开始,向中间移动。
适合:反转数组、判断回文、两数之和有序版。
2. 快慢指针
两个指针从同一方向出发,移动速度不同。
适合:链表是否有环、删除重复、移动零。
3. 同向双指针
两个指针都向右移动,一个维护窗口或结果位置。
适合:滑动窗口、数组原地修改。
二、反转字符串
def reverse_string(s):
chars = list(s)
left, right = 0, len(chars) - 1
while left < right:
chars[left], chars[right] = chars[right], chars[left]
left += 1
right -= 1
return "".join(chars)
这是左右指针最基础应用。
三、判断回文
def is_palindrome(s):
left, right = 0, len(s) - 1
while left < right:
if s[left] != s[right]:
return False
left += 1
right -= 1
return True
边界:空字符串、单字符、奇偶长度。
四、移动零
要求把数组中的 0 移到末尾,保持非零元素相对顺序。
def move_zeroes(nums):
slow = 0
for fast in range(len(nums)):
if nums[fast] != 0:
nums[slow], nums[fast] = nums[fast], nums[slow]
slow += 1
return nums
slow 指向下一个非零元素应该放的位置,fast 用于扫描数组。
五、合并两个有序数组
def merge_sorted(a, b):
i = j = 0
result = []
while i < len(a) and j < len(b):
if a[i] <= b[j]:
result.append(a[i])
i += 1
else:
result.append(b[j])
j += 1
result.extend(a[i:])
result.extend(b[j:])
return result
两个指针分别指向两个数组当前待比较元素。
六、删除有序数组重复项
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
slow 维护去重后数组的最后位置,fast 扫描新元素。
七、链表是否有环
快慢指针经典题:快指针每次走两步,慢指针每次走一步,如果有环一定会相遇。
def has_cycle(head):
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow == fast:
return True
return False
边界:空链表、单节点、无环、有环。
八、双指针常见错误
1. 循环条件写错
左右指针常用 left < right,链表快慢指针要判断 fast 和 fast.next。
2. 指针移动遗漏
某个分支忘记移动指针会死循环。
3. 交换顺序错误
原地修改时要注意不要覆盖数据。
4. 没有处理空输入
数组、字符串、链表都要考虑空。
九、面试回答模板
如果面试官问“双指针题怎么理解”,可以这样回答:
双指针是用两个指针协同移动来降低复杂度或实现原地操作。常见有左右指针、快慢指针和同向双指针。左右指针适合反转字符串、判断回文;快慢指针适合链表是否有环;同向双指针适合移动零、删除有序数组重复项和滑动窗口。写双指针题时,我会特别注意循环条件、指针移动和空输入边界,避免死循环和越界。
十、练习清单
- 反转字符串;
- 判断回文;
- 反转数组;
- 移动零;
- 删除有序数组重复项;
- 合并两个有序数组;
- 有序数组两数之和;
- 链表是否有环;
- 找链表中点;
- 复述三类双指针。
双指针题的关键是明确两个指针各自代表什么,以及什么时候移动。讲清这个,代码就不容易乱。
配套刷题:

