LeetCode-142

环形链表

给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

思路: 快慢指针,快指针一次走两步,慢指针一次走一步,如果存在环,快指针会再环内追上慢指针

/**
 * 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(fast && fast->next)
		{
    
    
			slow = slow->next;
			fast = fast->next->next;
			if(slow == fast)      //如果链表存在环
			{
    
    
				fast = head;
				while(fast != slow)//第二次相遇即为环的入口
				{
    
    
					fast = fast->next;
					slow = slow->next;
				}
				return fast;
			}
		}
		return NULL;
	}
};

题解

在这里插入图片描述
其中【*】为快慢指针首次相遇点,入环前距离为【D】,慢指针入环后走过的距离为【S1】,环剩下距离为【S2】

首次相遇
1.慢指针 S = D + S1
2.快指针 F = D + n(S1 + S2) + S1 其中n>=1,快指针起码走了一圈以上才可能相遇
3.又因为 F = 2S 慢指针走一步,快指针走两步
4.代入1,2 可得 2(D + S1) = D + n(S1 + S2) + S1
各种移项可得 D = (n-1)S1 + nS2 = (n-1)(S1 + S2) + S2
5.其中 n为快指针绕的圈数
n=1 D = S2
n=2 D = 一圈 + S2
n=3 D = 两圈 + S2

所以其实我们并不关心绕了多少圈,就知道 n圈+S2就是入环点了
6.人为构造碰撞机会,让快指针重新出发(但这次一次走一步),只要碰撞了,就是入环位置了,管他慢指针在环里绕了多少圈

参考文章
LeetCode 链接

猜你喜欢

转载自blog.csdn.net/GreedySnaker/article/details/115114112
142