环形链表的问题

一、什么是环形链表

        你是否也见到过这样的链表,这种链表结构非常简单,只是让单链表的尾节点指向其中的某个节点,如果连续跟踪next指针,则会陷入循环当中。这就是环形链表。

二、如何判断一个链表中是否有环

1、哈希表

        最容易想到的是方法是遍历所有的结点,每遍历一个节点,判断该节点此前是否被访问过。我们可以使用使用哈希表储存所有已经访问过的节点,每遍历到一个节点时,如果该节点已经存在于哈希表中,则说明该链表是环形链表,否则就将该节点加入哈希表中。重复这一过程,直到遍历完该链表为止。

2、快慢指针

        还有一种方法是用快慢指针遍历链表,快指针一次走两个节点,慢指针一次走一个节点,如果两个指针可以相遇,则说明该链表是环形链表,如若快指针走到空,则该链表不是环形链表。

问题:(1)环形链表中为什么快慢指针可以相遇?

           (2)快指针只能一次走两个节点吗?

        先看第一个问题,我们先将快指针命名为fast,慢指针命名为slow,设slow在环内走过的节点为n,则fast在环内走过的节点为2n,环内的总结点数为c,当2n - n = c时,则两个指针相遇。第二个问题,若快指针一次走三个节点,则有3n - n = c,即c = 2n,也就是说环内的总结点数为偶数时两个指针才会相遇。以此类推fast一次走四个节点,c = 3n...... 

        总之,当环内的总结点数等于两个指针走的节点数差值的倍数时,两个指针才会相遇,因此我们选用fast一次走两个节点。

三、找到环形的第一个节点

        上面一个问题相对简单,而这个问题则需简单的证明,具体过程如下:

 

 

     设fast走过的距离为l + x + n*c,slow走过的距离为l + x,则有l + x + n*c = 2*(l + x),即l = n*c - x = (n-1)*c + c - x,也就是说让另一个指针first从头走,slow从相遇点走,两个指针一次走一个节点,会在环形的第一个节点相遇。

具体的代码如下:

struct ListNode *detectCycle(struct ListNode *head) {
   
    struct ListNode *fast,*slow;
    fast = slow = head;

    while(fast && fast->next)
    {
        fast = fast->next->next;
        slow = slow->next;

        if(slow == fast)
        {
            struct ListNode *first = head;

            while(first != NULL)
            {
                if(first == slow)
                {
                    return first;
                }
                first = first->next;
                slow = slow->next;
            }

        }

    }

    return NULL;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值