[leetcode-142]Linked List Cycle II(c)

本文介绍了一种在不使用额外空间的情况下,解决寻找循环链表起始节点问题的方法,通过快慢指针技巧,实现高效求解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述:
Given a linked list, return the node where the cycle begins. If there is no cycle, return null.

Follow up:
Can you solve it without using extra space?

分析:这个题比上个题稍微复杂一点,这里要分为三步:第一步,判断是否有环,第二,如果有环,找到环的长度。第三,使用快慢指针,间距分别为环的长度,同时运动,当两者相等时,该点为环的起始点。

代码如下:4ms

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *detectCycle(struct ListNode *head) {
     if(!head)
        return NULL;

     struct ListNode *slow = head,*fast = head->next;

     while(slow && fast){
         if(slow==fast)
            break;
        slow = slow->next;
        fast = fast->next;
        if(!fast)
            break;
        fast = fast->next;
     }
     if(slow!=fast)
        return NULL;

    //check the length of circle
    fast = slow->next;
    int length = 1;
    while(fast!=slow){
        length++;
        fast = fast->next;
    }

    slow = head;
    fast = head;

    while(length--){
        fast = fast->next;
    }
    while(slow!=fast){
        slow = slow->next;
        fast = fast->next;
    }
    return slow;
}

在网上看到了很巧妙的一种方法:思路是这样的,因为快指针每次运动2,慢指针每次运动1,所以当出现环时,快慢指针一定会相遇,在相遇的位置时,快指针运动了2m,慢指针运动了m,那么2m-m=m就是环长度的整倍数。
假设此时,一个指针从头开始出发,一直运动m,那么还是会运动到相遇点,而另一个指针从当前位置出发,经过m,同样会运动到相遇点。当然,此时二者的运动速度都是1,那么当两个指针都进入环之后将会保持一致相对静止,所以除非在进入环的一刻二者就保持相等。否则我们上面的结论是不可能出现的。

代码如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *detectCycle(struct ListNode *head) {
    if(!head)
        return NULL;

    struct ListNode *s = head,*f = head;   
    while(f){
        if(f) f = f->next;
        if(f) f = f->next;
        if(s) s = s->next;

        if(s == f)
            break;
    }
    if(!f)
        return NULL;

    s = head;
    while(f!=s){
        f = f->next;
        s = s->next;
    }
    return s;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值