双指针指在遍历对象的过程中,不是普通的使用单个指针进行访问,而是使用两个相同方向(快慢指针)或者相反方向(对撞指针/左右指针)的指针进行扫描,从而达到相应的目的,常用于链表或有序数组中:双指针法充分使用了链表指向/数组有序这一特征,从而在某些情况下简化一些运算。
对撞指针
对撞指针(左右指针)是指在有序数组中,将指向最左侧的索引定义为左指针 left
,指向最右侧的索引定义为右指针 right
,然后从两头向中间进行数组遍历:
1 | def twoPointer(nums): |
快慢指针
快慢指针也是双指针,但是两个指针从同一侧开始遍历数组,将这两个指针分别定义为快指针 fast
和慢指针 slow
,两个指针以不同的策略移动,直到两个指针的值相等或快指针到达数组末尾(或其他特殊条件)为止,移动策略包括但不限于以下几种:
fast
每步移动两次,slow
每步移动一次:该策略常用于解决链表中的一些问题,例如 LeetCode 141.环形链表 中判断给定链表中是否存在环;fast
先行移动一定的步数,然后fast
与slow
一起移动:例如 链表中倒数第 k 个节点;fast
用于遍历整个有序数组,遍历过程中指向待处理序列的头部;同时slow
用于标记已满足题目条件的序列,slow
左边的序列已经满足题目给出的要求:该策略常用于需要对有序数组本身进行 in-place 处理,使该数组满足某些条件的问题,例如 LeetCode 283. 移动零 以及 LeetCode 26. 删除有序数组中的重复项 等;
上述第三种策略的模板如下:
1 | def twoPointer(nums): |