有环链表中寻找到环的起点

用2个辅助指针,第一个指针p1每次走一步,第二个指针p2每次走两步。当p1走到环的起点时走了a步,那么p2肯定在环中,而且走了2a步,距离环的起点是2a-a步。如果p1再走b步与p2相遇,那么就会有这么一个等式

a + b = 2 * (a + b) - k * n

其中,k就是b在环中走的圈数,n是环的长度。因为相遇时可能p2在环中走了k圈了.上述等式可以转换为下式

a + b = k * n

这时,把p1拉回链表起点,p2留在相遇点。p1和p2每次都走一步,那么当p1走了a步后,也就是环的起点时,p2也走了a步,但是因为p2已经在环的b位置,那么再走a步后,根据上面的公式,就会发现p2走到了环的起点。因为p1也在环的起点,所以2个指针就会相遇,而相遇点就是环的起点。
代码如下:

struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
    ListNode *p1 = head, ListNode *p2 = head;
    do {
        if ((p2 == 0) || (p2->next == 0)) 
            return 0;
        p2 = p2->next->next;
        p1 = p1->next;
    } while (p1 != p2);
    //把p1拉回起点
    for (p1 = head; p1 != p2; p1 = p1->next, p2 = p2->next);
    return p1;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值