环形链表(成环的相交的节点在哪)(中等)(证明题)
题目
解题思路(证明一下)
1,找到环形链表里面的相交节点,所以我们设立快慢指针
- slow,fast
- 所以2slow=fast
- 所以slow=slow->next;
- 所以fast=fast->next->next;
2,快慢指针节点相交之后,初始节点到入环那么长的距离,刚好相交
3,所以我们假设:
- 初始节点到入环那么长的距离==L
- 环的周长为R
- 入环到相遇的节点为S
- 相遇节点到入环距离为T
4,这里的关键点在于你需要证明L==T然后就可以解题
这里需要注意的几个点就是,
1,是slow是不会走第二圈的,所以相遇时候慢指针走的距离是L+S。
- 首先这里是一定相遇的
- 其次快指针在追击慢指针,并且至少是慢指针的两倍,我们这里设定的是两倍,慢指针进环的时候,首先不确定快指针走几圈,可能是x圈数,也就是x*R
- 慢指针就算第一圈没有相遇,第二圈也一定相遇,此时慢指针依旧在圈里面,所以慢指针的路程就是L+S
2,x(走的圈数),不可能等于0
- 除非是空链表,或者不是成环的,但是显然这个题目已经确定成环的,所以快指针一定进环,并且至少走一圈才能相遇,所以x至少等于1,不可能等于0
- 此时不管x是多少,其实本质都不影响最后的结果,所以最后还不如直接设定为x==1,方便计算
3,假设x==2,那么我们此时x走完一圈之后,减去S,那么剩余的是T,那么我们依旧可以计算出S==T
所以
4,最后设立两个新节点,前进,相遇的时候就是第一个相交的节点
代码
/** * Definition for singly-linked list. * struct ListNode { * int val; * struct ListNode *next; * }; */ typedef struct ListNode ListNode; ListNode *detectCycle(ListNode *head) { ListNode* fast = head; ListNode* slow = head; while(fast && fast->next) { fast = fast->next->next; slow = slow->next; if(fast == slow) { ListNode* cur = head; ListNode* meet = slow; while(cur != meet) { cur = cur->next; meet = meet->next; } return meet; } } return NULL; }