lintcode 带环链表2

本文介绍了一种高效的算法,用于在链表中查找环的起始节点。通过使用快慢指针技巧,该算法能在不使用额外空间的情况下确定环的入口。文章详细解释了算法的原理,并提供了完整的代码实现。

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

lintcode 带环链表2

描述

给定一个链表,如果链表中存在环,则返回到链表中环的起始节点,如果没有环,返回null。

样例

给出-21->10->4->5,返回10
解释:
最后一个节点5指向下标为1的节点,也就是10,所以环的入口为10

挑战

不使用额外的空间

思路

和带环链表找环一样,使用快慢指针,当fast == slow的时候,就说明有环了。此时通过数学计算可以证明此时slow指针走的步数等于环的长度。证明如下:
设slow指针走了i,则fast走了2i,再设环外长度为m,环长为n,则有如下的等式
(i-m)≡(2i-m)(mod n)
第一次相遇时(不包括第一次在head处)i-m=n-m,2i-m=2n-m,可以得到i = n.
也就是说,此时在环内已经走了n-m的长度,剩下m的长度。于是此时可以让slow从head处开始走,fast的步长变为1,再继续走,再次相遇时,就是环的入口。

代码

/**
 * Definition of singly-linked-list:
 * class ListNode {
 * public:
 *     int val;
 *     ListNode *next;
 *     ListNode(int val) {
 *        this->val = val;
 *        this->next = NULL;
 *     }
 * }
 */

class Solution {
public:
    /**
     * @param head: The first node of linked list.
     * @return: The node where the cycle begins. if there is no cycle, return null
     */
    ListNode * detectCycle(ListNode * head) {
        // write your code here
        if (!head || !head->next) return false;
        ListNode *fast = head->next->next, *slow = head->next;
        int index;
        while (fast && fast->next) {
            if (fast == slow) {
                slow = head;
                while (slow != fast) {
                    slow = slow->next;
                    fast = fast->next;
                }
                return fast;
            }
            fast = fast->next->next;
            slow = slow->next;
            index++;
        }
        return NULL;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值