Linked List Cycle(find the start node)---142--找到環的起始點

題目描述:找到鏈表中環節點

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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章