<LeetCode OJ> 141 / 142 Linked List Cycle(I / II)

Given a linked list, determine if it has a cycle in it.

Follow up:
Can you solve it without using extra space?


分析:
如果有环?遍历链表将无法走完,如果无环终会走到尾为NULL的位置
让一个指针每次走一个,一个指针每次走两个位置,
如果其中一个为NULL则无环,
如果相遇(必会相遇)了则有环。

time,o(n),space,o(1)

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */

class Solution {
public:
    bool hasCycle(ListNode *head) {
        if(head==NULL)
            return false;
        ListNode *showNode=head;
        ListNode *fastNode=head;
        while(true)
        {
            if(showNode->next!=NULL)
                showNode=showNode->next;
            else
                return false;
            if(fastNode->next!=NULL && fastNode->next->next!=NULL)    
                fastNode=fastNode->next->next;
            else
                return false;    
            if(showNode==fastNode)
                return true;
        }
        return false;
    }
};


别人的简洁算法:一样的思路

class Solution {
        public:
            bool hasCycle(ListNode *head) {
                ListNode *slow=head,*fast=head;
                while(slow&&fast&&fast->next){
                    slow=slow->next;  //跑的慢
                    fast=fast->next->next;  //跑的快
                    if(slow==fast) return true; //相遇则有环
                }
                return false;
    }
};




Given a linked list, return the node where the cycle begins. If there is no cycle, return null.

Note: Do not modify the linked list.

Follow up:
Can you solve it without using extra space?


分析:


1). 使用快慢指针法,若链表中有环,可以得到两指针的交点M
2). 记链表的头节点为H,环的起点为E

2.1) L1为H到E的距离
2.2) L2为从E出发,首次到达M时的路程
2.3) C为环的周长
2.3) n为快指针在环中所绕圈数


根据L1,L2和C的定义,我们可以得到:
慢指针行进的距离为L1 + L2
快指针行进的距离为L1 + L2 +  n*C

由于快慢指针行进的距离有2倍关系,因此:
2 * (L1+L2) = L1 + L2 +  n*C => L1 + L2 =  n*C => L1 = (n-1)*C+ C - L2
可以推出H到E的距离 = 从M出发绕n-1圈后到达E时的路程
因此,当快慢指针在环中相遇时,我们再令一个慢指针从头节点出发
接下来当两个慢指针相遇时,即为E所在的位置

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode *slow=head,*fast=head;  
        while(slow && fast && fast->next){  
            slow=slow->next;  //跑的慢  
            fast=fast->next->next;  //跑的快  
            if(slow==fast) break; //相遇则有环  
        }
        if(fast==NULL || fast->next==NULL)
            return NULL;
        
        fast=head;
        while(slow != fast){  
            slow=slow->next;  //一样的速度跑 
            fast=fast->next; 
        }
        return slow;
    }
};



注:本博文为EbowTang原创,后续可能继续更新本文。如果转载,请务必复制本条信息!

原文地址:http://blog.csdn.net/ebowtang/article/details/50507131

原作者博客:http://blog.csdn.net/ebowtang

本博客LeetCode题解索引:http://blog.csdn.net/ebowtang/article/details/50668895

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值