leetcode.环形链表问题

目录

题目1

示例

解题思路

代码实现

补充

题目2

示例

解题思路

代码实现


题目1

66360b0d1ac6496e9f4195ae0fb6a0e0.jpg

该题链接:https://leetcode.cn/problems/linked-list-cycle/description/

示例

ff1e1d3a4c744212b2a3814f99f6165f.png

cd707a3f7848435781f3138a894e2e3c.png

解题思路

     要创建两个指针一个是快指针(fast),另一个慢指针(slow)。快指针走两步慢指针走一步,让它们一起往后走,如果它们相等即存在环。

     为什么它们相等即存在环呢?

     我们先假设一个链表存在环。让fast和slow一起从起始位置走。fast肯定先进环。当slow走到环的入口处时,假设fast与slow的距离为N。fast走两步,slow走一步,这时N会变成N-1。只要它们一直走,N一定会等于零,这时候它们相遇,即存在环。

代码实现

     这里着重讲一下循环结束条件。

  • 如果没有环,因为fast走的快所以它会先遇到NULL。要另外加上fast->next这是为了防止对NULL进行解应用。
  • 如果有环直接返回即可。
typedef struct ListNode ListNode;
bool hasCycle(struct ListNode *head) {
    ListNode* slow = head,*fast = head;
    while(fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
        if(slow == fast)
            return true;
    }
    return false;
}

补充

     为什么快指针要走两步走三步不行吗?四步呢?n步呢?这里我介绍fast走三步的情况。

     假设环的总长度为C。根据上面我介绍的如果N为奇数第一轮它们不会相遇。第二轮它们的距离是C-1,如果C-1是奇数那它们就永远就遇不到了。

总结一下:

     1、N是偶数,第一轮就追上了

     2、N是奇数,第一轮追击会错过,距离变成C-1

          a、如果C-1是偶数,下一轮就追上了

          b、如果C-1是奇数 那么就永远追不上 

     同时存在N是奇数且C是偶数,那就永远追不上

     让我们来证一下

     假设现在slow现在在入环口。设slow走的距离为L ,fast走的距离为L+X*C+C-N(X是fast在环里转的圈数)。

6f3f80a72536484e86433e6cd0db284f.png

     因为3slow=fast。所以3L=L+X*C+C-N。化简得2L=(X+1)C-N。

     分析:2L为偶数,将上面的不存在条件带入会发现该等式并不成立,所以走三步会遇到。

题目2

该题链接:https://leetcode.cn/problems/linked-list-cycle-ii/description/ 

示例

解题思路

     先设个快慢指针如果存在环则它们一定会相遇,当它们相遇时设一个meet指针指向它们相遇位置,在设一个head指针指向链表头节点。让它们同时走每次走一步,当它们相等时即找到入环的节点。

     解释:假设从头结点到入环节点距离为L,入环节点到fast和slow的相遇点距离为N。

      fast走的距离L+X*C+N(X是圈数),slow走的距离L+N。因为2slow=fast得

      2(L+N)=L+X*C+N,化简得:L=(X-1)C+C-N。即L=C-N。

代码实现

typedef struct ListNode ListNode;
struct ListNode *detectCycle(struct ListNode *head) {
    ListNode* slow = head, *fast = head;
    while(fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
        if(slow == fast)
        {
            ListNode* meet = slow;
            while(meet != head)
            {
                meet = meet->next;
                head = head->next;
            }
            return meet;
        }
    }
    return NULL;
}

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值