leetcode142. Linked List Cycle II

题目:题目链接

题目大意:判断链表是否有环,如果有环就找出环的入口

思路:快慢指针。举个例子假设A和B都想从宿舍去操场跑步,A跑的速度是B的两倍,那么当A在操场跑步时,B可能还没到操场。但B到了操场A肯定还在操场。此时就变成了小学操场追人的问题,因为你们速度不一样,你们总会相遇的。

需要解决两个问题:1.如何判断有无环。2.如何找到环的入口。

开始解题:快慢指针可以判断 有无环,如果没环快指针肯定会指向null。那么问题变成了怎么找环的入口?
如下:

利用快慢指针,快指针比慢指针多走一步。
假设从起点到环的入口走了a步,然后走了b步到相遇点。那么此时慢指针走了a+b步,快指针走了2(a+b)步。而此时快指针也就走了a+b+kL(k为圈数L为环长)。注意:假设从相遇点到入口有c步,那么b+c=L。那么可以列式:
2 ( a + b ) = a + b + k L 且 b + c = L 2(a+b) = a+b+kL 且 b+c=L 2(a+b)=a+b+kLb+c=L
代人:
a = ( k − 1 ) L + c a=(k-1)L+c a=(k1)L+c

因为已知相遇点走了c步就到了环的入口,那么多走(k-1)L圈也能到入口,所以从相遇点走a (a=c+(k-1)L)步也能到环的入口。因为不知道a的长度,所以只要让一个指针从起点开始走,一指针从相遇点开始走,两者相遇就说明该点是环的入口。
这里的证明参考我之前的一篇回答:证明
所有,两个问题都解决了,那么看代码吧:

/**
 * 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) {
		if (!(head && head->next)) return nullptr;//head,head->next有一个为空就表示不可能有环
		ListNode* slow = head;
		ListNode* fast = head;
		while (fast && fast->next) {//快慢指针走起来
			slow = slow->next;
			fast = (fast->next)->next;//走两步哦
			if (fast == slow) {//代表有环
				slow = head;//一个从起点走,一个从相遇点走
				while (fast != slow) {//这里不是快慢指针哦,是两个指针一样快
					slow = slow->next;
					fast = fast->next;
				}
				return slow;//走到环的入口
			}
		}
		return nullptr;//没有环
	}
};

加油加油加油加油!!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值