【Leetcode】142. Linked List Cycle II

题目地址:

https://leetcode.com/problems/linked-list-cycle-ii/

链表求环,如果有环,返回环的入口,否则返回null。经典快慢指针算法。先用快慢指针判断有没有环,见https://blog.csdn.net/qq_46105170/article/details/104013645,然后重新设一个节点cur等于head,接着cur和slow同时出发,每轮循环走一步,直到相遇。则相遇点即为环的入口。代码如下:

public class Solution {
    public ListNode detectCycle(ListNode head) {
        if (head == null || head.next == null) {
            return null;
        }
        
        ListNode slow = head, fast = head;
        do {
            slow = slow.next;
            fast = fast.next.next;
        } while (fast != null && fast.next != null && slow != fast);
        // 说明无环
        if (slow != fast) {
            return null;
        }
        
        ListNode cur = head;
        while (cur != slow) {
            cur = cur.next;
            slow = slow.next;
        }
        
        return cur;
    }
}

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

时间复杂度 O ( n ) O(n)

算法正确性证明:
设链表有环,链表的nodes是这样排列: v 1 v 2 . . . v k 1 v k v k + 1 . . . v k + s v k v_1\rightarrow v_2 \rightarrow ...\rightarrow v_{k-1} \rightarrow v_k\rightarrow v_{k+1}\rightarrow ...\rightarrow v_{k+s}\rightarrow v_k 也就是说从 v k v_k v k + s v_{k+s} 形成一个环,环的边数为 s + 1 s+1 。我们对于slow和fast各自走了多少步做分析。当slow走到 v k v_k 时,它走了 k 1 k-1 步,而fast走的步数是slow的两倍,所以fast走了 2 ( k 1 ) 2(k-1) 步,fast所处于的位置的下标是 k + ( k 1 )   %   ( s + 1 ) k+(k-1)\ \%\ (s+1) 。设slow再走 x x 步就与fast相遇,那么有同余式: x 2 x + k 1 m o d    ( s + 1 ) x\equiv 2x+k-1\mod (s+1) 所以 x + k 1 0 m o d    ( s + 1 ) x+k-1\equiv 0\mod (s+1) 也就是说slow再走 k 1 k-1 步就到达了 v k v_k ,而新的节点cur从head出发同时走 k 1 k-1 步正好也会走到 v k v_k ,所以相遇点就是环的入口。

发布了86 篇原创文章 · 获赞 0 · 访问量 1204

猜你喜欢

转载自blog.csdn.net/qq_46105170/article/details/104015181