題目描述:找到鏈表中環節點
input : 3->2->0->-4 ->2 output : 1
思路:找到頭節點和相遇點到環起始點的關係,可以證明相遇點到環起始點和頭節點到環起始點的距離相等
證明:頭節點到環節點距離x,環節點到相遇點y,相遇點到環節點z,快指針走的距離是慢指針的2倍
S慢 = x + y + nC S快 = 2S慢 = x + y + mC = 2x + 2y + 2nC
x = (m - 2n)C - y = (m - 2n - 1)C + C - y =(m - 2n - 1)C + z
所以當相遇的時候,一個指針從頭節點開始走,一個指針從相遇點開始走,再次相遇的位置就是環節點,因爲他們都走過了很多圈+z的距離
#include<iostream>
using namespace std;
struct ListNode{
int data;
ListNode* next;
ListNode(int x) : data(x), next(NULL){}
};
void show(ListNode* head)
{
if(head == NULL)
{
cout << "NULL";
}
ListNode* p = head;
while(p)
{
cout << p->data;
p = p->next;
if(p->data == head -> data)//加個判斷環中的元素打印完就退出。
break;
}
cout << endl;
}
ListNode* createList(int n)//尾插法創建鏈表
{
ListNode* head = new ListNode(0);
ListNode* newNode;
ListNode* rear = head;
for(int i = 0; i < n; i++)
{
int data;
cin >> data;
newNode = new ListNode(data);
rear->next= newNode;
rear = newNode;
}
rear->next = head->next;//讓最後一個元素指向頭節點,形成環
return head->next;
}
class Solution{
public:
ListNode* findStartNode(ListNode* head)
{
ListNode* fast = head, *slow = head;
while(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
if(slow == fast) break;
}
if(!fast || !fast->next) return NULL;
slow = head;
while(slow != fast)//慢指針從頭開始走
{
slow = slow->next;
fast = fast->next;
}
return fast;
}
};
int main()
{
ListNode* l = createList(4);
show(l);
Solution s;
ListNode *l1 = s.findStartNode(l);
show(l1);
return 0;
}