判断单链表中是否有环等相关问题

1.如何判断一个链表是否有环?

  • 采用快慢指针的思路,慢指针一次移动一个结点,快指针一次移动两个结点,如果有环,则进入环后,快指针肯定可以追赶上慢指针,这样就会出现两者相等的情况,从而得出有环。

  • 如何证明如果有环,进入环后,快指针一定会追上慢指针?

    证明:快指针先进入环,慢指针后进入环,假设在慢指针进入环之后与快指针之间的初始相差距离为 K。但是随着快指针与慢指针的移动,它们之间相差距离逐渐为 K , K-1,K-2, K-3…1, 0 当相差距离为 0 时,快指针追上慢指针。

  • 代码实现判断一个链表是否有环(例子:Leetcode第141题)

/**
 1. Definition for singly-linked list.
 2. struct ListNode {
 3.     int val;
 4.     struct ListNode *next;
 5. };
 */
typedef struct ListNode ListNode;//sp是慢指针,fp是快指针
bool hasCycle(struct ListNode *head)
{
    ListNode* sp = head;
    ListNode* fp = head;
    while(fp != NULL&&fp->next != NULL)
    {
        sp = sp->next;
        fp = fp->next->next;
        if(sp == fp)
            return true;
    }
    return false;
}

2.证明链表存在环,则 fast 和 slow 两指针必然会在 slow对链表完成一次遍历之前相遇。

首先引入一个图,方便用来分析:
在这里插入图片描述
证明:slow首次在A点进入环路时,fast一定在环中的B点某处。设此时slow距链表头head长为x,B点距A点长度为y,环周长为s。因为 fast 和 slow 的步差为1,每次追上1个单位长度,所以slow前行距离为y的时候,恰好会被fast在M点追上。因为y<s,所以slow尚未完成一次遍历。

3.如果链表存在环,如何求环的入口结点?

再引入一个图,方便用来分析:
在这里插入图片描述

  • 如果链表存在环,则fast和slow两指针必然会在slow对链表完成一次遍历之前相遇,设此时第一次相遇点为a点,此时 slow 走的距离为 L+X ,fast 走的距离为 L+X+N * C (ps:N为圈数,N>=1)。又因为快指针走的距离是慢指针的 2 倍,所以有:2(L+X)= L+X+NC (N>=1),既可以得到:L=NC-X。若此时再设置一个指向头节点的指针 p ,而slow 在 a 点处,当 p 走了 L 来到 b 点时,a 走了 q=N*C-X,恰好也来到 b 点处,此时,2个指针相遇了。相遇的点即为环的入口结点,如果定义一个 count ,可以算出 L 的长度。
  • 代码实现求环的入口结点(例子:Leetcode第142题)
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
typedef struct ListNode ListNode;
ListNode* Meet(ListNode* phead)
{
    ListNode* sp = phead;
    ListNode* fp = phead;
    while(fp != NULL&&fp->next != NULL)
    {
        sp = sp->next;
        fp = fp->next->next;
        if(sp == fp)
            return fp;
    }
    return NULL;
}
struct ListNode *detectCycle(struct ListNode *head)
{
     //快慢指针相遇点到入环点的距离 = 头结点到入环点的距离
    ListNode* meetnode = Meet(head);
    if(meetnode == NULL)
        return NULL;
    ListNode* sp = head;
    while(sp != meetnode)
    {
        sp = sp->next;
        meetnode = meetnode->next;
    }
    return sp;
}

4.如何求环的长度

  • fast 指针与 slow 指针在第一次相遇后,现在让 fast 不动, 继续让 slow 走。直到 slow 与 fast 再次相遇时,定义的 count 就为 结点数,即为环的长度。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值