环形链表II

2023-11-13

原题链接
本题要求找到环的入口,且 O ( n ) O(n) O(n)的时间复杂度, O ( 1 ) O(1) O(1)的空间复杂度。
参考了很是充分证明的题解,很多疑惑得到了解决

  • 先判断是否有环:快慢指针fastslow,直到两者第二次相遇的时候那么判断确定有环。(第一次是在起点)

  • 考虑如何找到入口,设 h e a d head head到链表环入口的结点数是 a a a,环的结点数是 b b b
    f = 2 s = s + n b f=2s=s+nb f=2s=s+nb,表示在 f f f s s s再次相遇时, f f f s s s多走了 n n n次环。
    f = 2 n b , s = n b f=2nb,s=nb f=2nb,s=nb
    那么所有到达链表入口的点都为 a + k b ( k ≥ 0 ) a+kb(k\geq0) a+kb(k0)

    考虑我们现在位置一为 o n e one one,从起点 h e a d head head开始,位置二 t w o two two s s s f f f相遇的那个结点。
    ,那么初始情况下 o n e = 0 one=0 one=0 t w o = n b two=nb two=nb
    所以当 o n e one one t w o two two都跑了 a a a步, o n e = a , t w o = n b + a one=a,two=nb+a one=a,two=nb+a,均符合入口为 a + k b a+kb a+kb的要求,即 o n e = a + 0 ∗ b ( k = 0 ) , t w o = a + n ∗ b ( k = n , n ≥ 0 ) one=a+0*b(k=0),two=a+n*b(k=n,n\geq0) one=a+0b(k=0),two=a+nb(k=n,n0),此时 o n e one one t w o two two都到达了入口

所以最后操作就是:
先快慢指针找到第一次相遇点,然后第二次分别从相遇点和起点开始直到相遇。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode* fast = head, *slow = head;
        while(fast != nullptr) {
            if(fast->next == nullptr || fast->next->next == nullptr) return nullptr;
            fast = fast->next->next;
            slow = slow->next;
            if(slow == fast) break;
        }
        
        ListNode* one = head, *second = slow;
        while(one != second) {
            one = one->next;
            second = second->next;
        }
        return one;
    }
};
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

环形链表II 的相关文章

随机推荐