定义
双指针,通常指的是在遍历数组对象时,使用两个指针进行扫描。根据指针前进的方向不同分为快慢指针(方向相同)和对撞指针(方向相反)。双指针利用了数组索引有序的特征从而简化某些情况下的处理。
对撞指针
对撞指针是指在有序数组中,将指向最左侧的索引定义为左指针,最右侧的索引定义为右指针,然后从两头向中间遍历。对撞指针适用于有序数组,可以考虑使用对撞指针来处理有序数组相关问题。
伪代码大致如下:
1 2 3 4 5 6 7 8 9 10
   | public void func(list) {     int left = 0;     int right = N - 1;          while (left <= right) {         left++;         .....         right--;     } }
  | 
 
快慢指针
快慢指针也是双指针,但是两个指针从同一侧开始遍历数组,将这两个指针分别定义为快指针(fast)和慢指针(slow),两个指针以不同的策略移动,一般快指针移动 2,慢指针移动 1,当两个指针的值相等(或其他特殊条件)移动停止。
伪代码大致如下:
1 2 3 4 5 6 7 8 9 10
   | public void func(Node node) {     Node slow = node;     Node fast = node;          while (slow.value != fast.value) {         slow = slow.next;         fast = fast.next.next;     }     return slow; }
  | 
 
快慢指针的应用
26 数组元素去重
1 2 3 4 5 6 7 8 9 10 11 12
   | public int removeDuplicates(int[] nums) {     if (nums.length == 0) return 0;     int i = 0;     for (int j = 1; j < nums.length; j++) {                  if (nums[j] != nums[i]) {             i++;             nums[i] = nums[j];         }     }     return i + 1; }
  | 
 
141 环形链表
1 2 3 4 5 6 7 8 9 10 11 12 13
   | public boolean hasCycle(ListNode head) {     if (head == null && head.next == null) return false;
      ListNode slow = head;     ListNode fast = head;
      while (slow != fast) {         slow = slow.next;         fast = fast.next.next;     }
      return slow; }
  | 
 
142 环形列表2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
   | public ListNode func(ListNode head) {     ListNode slow = head;     ListNode fast = head;          while (slow != fast) {         slow = slow.next;         fast = fast.next.next;         if (slow == fast) {             ListNode index1 = slow;             ListNode index2 = head;             while (index1 != index2) {                 index1 = index1.next;                 index2 = index2.next;             }             return index1;         }     }     return null; }     
  | 
 
160 相交链表
1 2 3 4 5 6 7 8 9 10 11 12 13
   | public ListNode getIntersectionNode(ListNode headA, ListNode headB) {     if (headA == null || headB == null) return null;          ListNode Pa = headA;     ListNode Pb = headB;          while (Pa != Pb) {         Pa = Pa == null ? headB : Pa.next;         Pb = Pb == null ? headA : Pb.next;     }          return Pa; }
  | 
 
链表二分
1 2 3 4 5 6 7 8 9 10 11
   | public ListNode EndOfFirstHalf(ListNode head) {          ListNode slow = head;     LsitNode fast = head;          while (fast.next != null && fast.next.next != null) {         slow = slow.next;         fast = fast.next.next;     }     return slow; }
  | 
 
参考
- 对撞指针——常用题型
 
- 算法一招鲜——双指针问题
 
- 数据结构和算法-双指针法