环形链表[快慢指针 & 入环点]

453 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第45天,环形链表[快慢指针 & 入环点] - 掘金 (juejin.cn)

前言

对于环问题,快慢指针是一种常用的手段。一步两步走,通过判定是否相遇来判定是否存在环。而且快慢指针还能轻松的求到入环点。

一、环形链表

image.png

二、快慢指针

1、相遇即有环

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    /*
    对于环问题,可采用快慢指针进行判定。
    快慢指针:慢指针走一步,快指针走两步,有环则两者相等,无环则快指针先到null。
    */
    public boolean hasCycle(ListNode head) {
        if(null == head) return false;

        ListNode slow = head,fast = head.next;

        while(slow != fast && fast != null){
            slow = slow.next;
            fast = fast.next;

            if(fast != null) fast = fast.next;
        }
        return fast == slow;
    }
    // 如果存在环,求入环节点怎么办?
    /*
    设起点到入环点的距离为a;设入环点到相遇点的距离为b;
    由于快指针是慢指针的2倍,所以除了快指针走的a+b,还剩a + b = k * L(L为环的长度,k为常数。);
    从环点走到相遇点,已经走了b了,再走距离为a时,共走了a+b=kL,则走了k圈回到起点。
    而起点到环点的距离也为a,所以从起点走到环点时,快指针也经走了k圈回到环点,两者相遇,得到环点。
     */
}

2、入环点

设起点到入环点的距离为a;设入环点到相遇点的距离为b;

由于快指针是慢指针的2倍,所以除了快指针走的a+b,还剩a + b = k * L(L为环的长度,k为常数。);

从环点走到相遇点,已经走了b了,再走距离为a时,共走了a+b=kL,则走了k圈回到起点。

而起点到环点的距离也为a,所以从起点走到环点时,快指针也经走了k圈回到环点,两者相遇,得到入环点。

总结

1)对于环问题,可采用快慢指针的相遇来判定是否存在环。

2)快慢指针不仅用于判定环,在对链表进行归并排序时,还可以取到链表的中点。

3)对于环入口问题,可再从起点行走,再次和快指针相遇时,则是入环点。

参考文献

[1] LeetCode 环形链表