LC 141,142 Linked List Cycle I / II 链表中的环

链表中的环是很经典的面试题,重要的是掌握链表类题目中快慢双指针的用法,不光可以用来解决环的探测,也可以解决其他的问题,例如查找链表中倒数第N个数,只要让fast比slow指针快N个节点,然后两个指针一起前进,当fast走到链表尽头,slow就指向倒数第N个节点(这道LC题前几天做到了,但是忘记是哪一道了)。

LC 141 Linked List Cycle

bool hasCycle(ListNode *head) {
	if(head==NULL||head->next==NULL)
		return false;
    ListNode *f=head,*s=head;
    while(f->next&&f->next->next){
    	f=f->next->next;
    	s=s->next;
		if(f==s)
			return true;
	}
	return false;
}

LC142 Linked List Cycle II

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?

我在代码里已经把解题思路写好了,这里就直接复制过来了。 

L1: distance from head to the entry point of cycle

 L2: distance from the entry point to meeting point
 C: number of points in the cycle
 When the slow pointer enters the cycle, if the cycle is long enough, the fast pointer is L1 points ahead of slow.
 Then the chase within cycle starts. The slow walks L2 steps and the fast walks 2 * L2 steps.
 We have this equation: place of fast + steps that fast walked - n loops == steps that slow walked, that is :
 L1 + 2 * L2 - n * C == L2   ===>    L1 + L2 == n * C
 ******IMPORTANT CONCLUSION******: distance from meeting point to entry point along the forward direction == L1
 If there is only one loop, then L1 + L2 == C, or L1 = C - L2
 Therefore, if we start from the meeting point, let A start from head and B start from meeting point, both walks by one step,

 then A and b shall meet at the entry point of the cycle.

通过数学方法寻找到L1,L2和C的关系,在slow和fast相遇时,让a从head开始,b从相遇点开始,两个指针相遇的地方就是环开始的地方。知道这个结论之后就可以很简单的做出这道题了。所以感觉这道题更像一道数学题而不是链表题。

ListNode *detectCycle(ListNode *head) {
    ListNode *slow = head,*fast = head;
    while(slow != NULL && fast != NULL && fast->next != NULL) {
        slow = slow->next;               //Slow moves by 1 step
        fast = fast->next->next;        //Fast moves by two steps
        //If they meet then there is a loop
        if(slow == fast)
        {
            //To find the starting element where the loop starts
            fast = fast;
            slow = head;
            while(slow != fast)
            {
                //Both move by 1 step
                slow = slow->next;
                fast = fast->next;
            }
            return slow;
        }
    }
    return NULL;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值