zoukankan      html  css  js  c++  java
  • [LeetCode]Linked List Cycle

    题目:Linked List Cycle

    判断一个单链表中是否有环,要求常量空间复杂度;

    思路:

    使用两个指针同时从链表表头开始移动,一个移动一步,一个移动两步,直到两个指针重合或某一指针指向链尾。

    两个指针重合则单链表有环存在,否则没有。

    第二个指针以第一个指针的两倍的速度移动,而第一个指针每次移动一步,这样只要有环,两个指针必定能重合。

    bool LeetCode::hasCycle(ListNode *head){
        if (!head)return false;
        ListNode *p = head, *q = head;
        while (q){
            p = p->next;//p每次前进一步
            if (!q->next)return false;//q是否到链尾
            q = q->next->next;//q每次前进两步
            if (p == q)return true;//重合则有环
        }
        return false;
    }

    题目:Linked List CycleII

    如果一个单链表中有环,找到环的开始位置,没有则返回null;

    要求常量空间复杂度;

    思路:

    使用两个指针同时从链表表头开始移动,一个移动一步,一个移动两步,直到两个指针重合或某一指针指向链尾。

    如果两个指针重合,则跳出循环;

    然后将其中一个指针重新指向链头,两个指针每次移动一步,知道再次重合,此时重合位置必定为环头。

    证明:

    假设某单链表有环,不妨设链头到链表环开始位置的长度设为a,链表环的长度设为b;则链表的长度为a+b;

    先移动两指针直到第一次重合,

    一次移动一步的指针移动的步数:n = a + l*b + c
    一次移动两步的指针移动的步数:2n = a + k*b + c = 2(a + l*b + c)

    a + k*b + c = 2(a + l*b + c) => a + c = (k - l)b

    两个指针第一次相遇时,l = 0;

      可以用反证法证明:假设l = k0(k0不等于0)是第一次相遇时l的值,则a + c = (k - k0)*b;

      此时当l1 = 0,k1 = k - k0时,此时两个指针也会相遇,且l1 < l0,即l1是比l0还早的一次相遇,矛盾了。

    于是l = 0,则a + c = k * b;

    当前两个指针的位置为n = a + l*b + c = a + c(l = 0) = k * b;

    此时将其中一个指针重新指向链头,然后两个指针每次移动一步,直到再次相遇;

    此时,另一个指针沿着环移动到环头需要步数:k*b - c = a;(k >= 1)

    所以,两个指针第二次重合必定在环的开头位置。

    ListNode *LeetCode::detectCycle(ListNode *head){
        if (!head)return nullptr;
        bool hasCycle = false;
        ListNode *p = head, *q = head;
        while (q){
            p = p->next;//p每次前进一步
            if (!q->next)return nullptr;//q是否到链尾
            q = q->next->next;//q每次前进两步
            if (p == q){
                hasCycle = true;//重合则有环
                break;
            }
        }
        if (!hasCycle)return nullptr;
        p = head;//p再次从头直到与q重合,则当前位置为环的开始位置
        while (p != q){
            p = p->next;
            q = q->next;
        }
        return p;
    }
  • 相关阅读:
    UVA 465 Overflow (浮点数的优势)
    UVA 424 Integer Inquiry (大数相加问题)
    UVA 10494 If We Were a Child Again(大数与整型相除取整和取余)
    粘一个在UVA和ZOJ都能AC但POJ WR的代码
    UVA 340 MasterMind Hints
    UVA10815 Andy's First Dictionary
    MSComm写串口通信驱动步骤
    UVA 10106 Product (大数相乘问题)
    实现工具栏中添加的组合框接收回车消息
    UVA 10420 List of Conquests
  • 原文地址:https://www.cnblogs.com/yeqluofwupheng/p/6746209.html
Copyright © 2011-2022 走看看