快慢双指针法

介绍

快慢双指针是双指针问题的一种解决方案,主要用于解决链表相关的题目,而左右指针那种滑动窗口的算法主要是用于解决数组问题

应用

  • 快慢双指针可以用来判定链表中是否存在环
    一般而言,如果链表中存在环路,那么对于单链表的遍历就会陷入死循环,可以使用快慢双指针去遍历该链表,慢指针一步一步走,快指针一次走两步;
    那么如果快指针最终走到null节点,那么就是遍历完成;
    如果存在环路,那么快慢指针最终一定会相遇,因为快指针始终快于慢指针一倍的距离
boolean hasCycle(ListNode head) {
    ListNode fast, slow;
    fast = slow = head;
    while(fast != null && fast.next != null) {
        fast = fast.next.next;
        slow = slow.next;
        
        if (fast == slow)
            return true;
    }
    return false;
}
  • 找到链表中环路的起点
    当快慢指针第一次相遇的时候,就可以确定链表中存在环路,如果让其中一个节点回到起点再让快慢指针以同样速度前进,那么再次相遇就是环起点
ListNode detectCycle(ListNode head) {
    ListNode fast, slow;
    fast = slow = head;
    while (fast != null && fast.next != null) {
        fast = fast.next.next;
        slow = slow.next;
        if (fast == slow)
            break;
    }
    
    slow = head;
    while (slow != fast) {
        fast = fast.next;
        slow = slow.next;
    }
    return slow;
}
  • 寻找链表中点
    我们可以让快指针一次前进两步,慢指针一次前进一步,当快指针到达链表尽头时,慢指针就处于链表的中间位置。
ListNode slow, fast;
slow = fast = head;
while (fast != null && fast.next != null) {
    fast = fast.next.next;
    slow = slow.next;
}
// slow 就在中间位置
return slow;

当程序结束时,如果链表的长度是奇数时,slow 恰巧停在中点位置;如果长度是偶数,slow 最终的位置是中间偏右;可以利用这个方法去进行归并排序

  • 寻找链表的倒数第k个节点
    让快指针先走 k 步,然后快慢指针开始同速前进。这样当快指针走到链表末尾 null 时,慢指针所在的位置就是倒数第 k 个链表节点(假设 k 不会超过链表长度)
ListNode slow, fast;
slow = fast = head;
while (k-- > 0) 
    fast = fast.next;
 
while (fast != null) {
    slow = slow.next;
    fast = fast.next;
}
return slow;
posted @ 2020-09-06 16:22  珂珂哒  阅读(241)  评论(0)    收藏  举报