题目描述
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
方法1:
1)定义快慢指针,找出相遇节点。
2) 相遇后获取环中节点数量,即快指针不动,慢指针继续走,再次相遇时满指针刚好走了一个环,并且满指针继续走时将其插入vector中
3) 从链表头开始遍历,找到第一个vector中存在的节点即为入口环节点
class Solution {
public:
ListNode* EntryNodeOfLoop(ListNode* pHead)
{
if (pHead == NULL || pHead->next == NULL) return NULL;
ListNode *fast = pHead->next->next;
ListNode *slow = pHead->next;
while (fast != slow) // 遍历使快慢指针相遇
{
fast = fast->next->next;
slow = slow->next;
}
int count = 1;
vector<ListNode*> s;
s.push_back(slow);
slow = slow->next;
while (slow != fast) // 获取环中节点数量
{
s.push_back(slow); //环节点插入vector
slow = slow->next;
count++;
}
ListNode *temp = pHead;
while (true)
{
for (int i=0; i < s.size(); i++) // 查找入口节点
{
if (temp == s[i])return temp; // 第一个相等的即为入口结点
}
temp = temp->next;
}
return NULL;
}
};
方法二:
首先找到相遇节点,同方法一
链表头到环入口长度为--a
环入口到相遇点长度为--b
相遇点到环入口长度为--c
则:相遇时
快指针路程=a+(b+c)k+b ,k>=1 其中b+c为环的长度,k为绕环的圈数(k>=1,即最少一圈,不能是0圈,不然和慢指针走的一样长,矛盾)。
慢指针路程=a+b
快指针走的路程是慢指针的两倍,所以:
(a+b)*2=a+(b+c)k+b
化简可得:
a=(k-1)(b+c)+c 这个式子的意思是: 链表头到环入口的距离=相遇点到环入口的距离+(k-1)圈环长度。其中k>=1,所以k-1>=0圈。所以两个指针分别从链表头和相遇点出发,最后一定相遇于环入口。
class Solution {
public:
ListNode* EntryNodeOfLoop(ListNode* pHead)
{
ListNode*fast=pHead,*low=pHead;
while(fast&&fast->next){
fast=fast->next->next;
low=low->next;
if(fast==low)
break;
}
if(!fast||!fast->next)return NULL;
low=pHead;//low从链表头出发
while(fast!=low){//fast从相遇点出发
fast=fast->next;
low=low->next;
}
return low;
}
};
方法三:
1、断链法
ListNode× EntryNodeOfLoop(ListNode pHead)
{
if(pHead==null|| pHead.next==null)returnnull;
ListNode fast=pHead.next;
ListNode slow=pHead;
while(fast!=null)
{
slow.next=null;
slow=fast;
fast=fast.next;
}
return slow;
}
// 该方法修改了链表,若要求不能修改链表时就不能用了