判断一个单链表是否有环,如果有,找出环的起始位置

 第一种方法是从单链表head开始,每遍历一个,就把那个node放在hashset里,走到下一个的时候,把该node放在hashset里查找,如果有相同的,就表示有环,如果走到单链表最后一个node,在hashset里都没有重复的node,就表示没有环。 这种方法需要O(n)的空间和时间。


       第二种方法是设置两个指针指向单链表的head, 然后开始遍历,第一个指针走一步,第二个指针走两步,如果没有环,它们会直接走到底,如果有环,这两个指针一定会相遇。方法二的实现代码如下,程序中找出了环的起始位置:

node* first_loop_port(node *head)
{
    node *slow = head, *fast = head;

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

    if (fast == NULL || fast->next == NULL)
        return NULL;

    slow = head;
    while (slow != fast)
    {
         slow = slow->next;
         fast = fast->next;
    }

    return slow;
}

这里用到了一个巧妙的处理方法:

假设环长为L,起始点到环入口长度为a,环长度为r,设慢指针和快指针相遇前,慢指针在环内走了x步(快指针已经走了n圈),同时假设慢指针已经走了s步,则快指针走了2s步。
则有:2S = S + n r   ;则s = nr;

又 a + X  = S;故a+X = nr = (n-1)r+r = (n-1)r + L-a;则a = (n-1)r + L-a-X;含义为环入口距离起点的距离和相遇点距离环入口点的距离相等。

故让慢指针回到起点,快指针从相遇点开始继续走,当两者相等时,则为环入口地址。

【转自http://blog.csdn.net/yushuai007008/article/details/7644954】


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值