Linked List Cycle II--找出单向链表中环的起点

原题:

Given a linked list, return the node where the cycle begins. If there is no cycle, returnnull.

=>找到单向链表的环的起点,若没有环,返回null

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

=>能否不使用额外的空间。

/**
 * 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) {
        // IMPORTANT: Please reset any member data you declared, as
        // the same Solution instance will be reused for each test case.
        
    }
};


晓东分析:

看单向链表中是否存在环,晓东之前已经讲过了。这篇文章主要讲一下,如何找到这个环的起点,其实方法很简单,就是在快慢指针相交的时候,把快指针移到开始,然后大家都以1步的步长开始运动,再次遇到的时候就是环的起点。如何来证明这个做法呢,晓东来简单讲解一下。假设如下图:

我们假设快慢指针相会于C点。这个时候他们走过的路程:

快指针路程=慢指针路程+N*圆的周长=AB的距离+BC距离+M*圆的周长(M和N都是整数,不一定相等)

而我们知道快指针的路程,其实是慢指针路程的两倍。

也就是说:

快指针路程=2*慢指针的路程

所以2*慢指针的路程=慢指针路程+N*圆的周长

所以,慢指针路程=N*圆的周长。

代入上式得到:

2*N圆的周长=AB的距离+BC距离+M*圆的周长

所以AB的距离+BC距离=L*圆的周长

所以AB的距离= L*圆的周长-BC距离。

因此,我们从C点开始的慢指针,和从A点开始的慢指针肯定会相遇于B点。

代码实现:

/**
 * 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) {
        // IMPORTANT: Please reset any member data you declared, as
        // the same Solution instance will be reused for each test case.
        
        if(head == NULL || head->next == NULL) return NULL;
        
        ListNode *fast = head->next->next;
        ListNode *slow = head->next;
        
        while(fast != slow && fast != NULL && fast->next != NULL)
        {
            fast = fast->next->next;
            slow = slow->next;
        }
        if(fast == NULL || fast->next == NULL)
            return NULL;
        fast = head;
        while(fast != slow){
            fast = fast->next;
            slow = slow->next;
        }
        return fast;
    }
};

运行结果:

16 / 16test cases passed.
Status:
Accepted
Runtime: 68 ms

希望大家有更好的算法能够提出来,不甚感谢。

若您觉得该文章对您有帮助,请在下面用鼠标轻轻按一下“顶”,哈哈~~·

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值