判断链表中的环Floyd

0.006字数 410阅读 89

问题源于 leetcode 中的一道题:
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
就比方说下面这个图,就是返回那个红色的点


链表的数据结构:

class ListNode {
    int val;
    ListNode next;
    ListNode(int x) {
        val = x;
        next = null;
    }
}

算法介绍

  • 1 先定义两个指针,一个叫 fast,一个叫 slow,都指向链表中的第一个节点,
  • 2 fast 一次向前走两步(fast = fast.next.next),slow 一次走一步 (slow = slow.next)
  • 3 如果这个链表中有环,那 fast 一定会在一圈后追上 slow 点,它们会在某处相遇
  • 4 在相遇点,记录 slow 走过的路程为 x ,那么 fast 走过的路程就是 2x,即为 slow 再走 x 就与 fast 相同了
  • 5 再把 slow 走过的路程 x 分成 y + z ,y 表示从起始点到红点的路程,z 表示从红点到相遇点的路程
  • 6 那么把 4 和 5 结合起来看,让 slow 从相遇点再次开始走,它如果走 x ,它会回到自己的位置(由 4 得),而如果 slow 从红点开始走,走 z 会到达相遇点(由 5 得),那么它从相遇点开始走,走 y 就会回到红点,接下来确定 y 的位置就行了
  • 7 让 slow2 和 slow 同时开始走(slow2 = slow2.next; slow = slow.next;), 当它们同时走过 y,它们相遇的地方,就是红点

算法代码

public class Solution {
            //这里给出的是链表的头节点
            public ListNode detectCycle(ListNode head) {
                ListNode slow = head;
                ListNode fast = head;
                while (fast!=null && fast.next!=null){
                    fast = fast.next.next;
                    slow = slow.next;
                    
                    if (fast == slow){
                        ListNode slow2 = head; 
                        while (slow2 != slow){
                            slow = slow.next;
                            slow2 = slow2.next;
                        }
                        return slow;
                    }
                }
                return null;
            }
        }

源代码出自:https://leetcode.com/problems/linked-list-cycle-ii/discuss/44774/Java-O(1)-space-solution-with-detailed-explanation.

推荐阅读更多精彩内容