題目:如本文題目,給定一個帶環的單鏈表,給出一個算法求鏈表環的入口位置處的節點。 解析:這題的解決步驟如下: 1.設置一個快指針fast和一個慢指針slow,它們同時從鏈表頭開始往後遍歷,快指針每次移動兩個位置,慢指針每次移動一個位置 2.當快指針和慢指針相遇時,將慢指針重新指向鏈表頭 3.快指針和慢指針此時在同時移動,兩個指針都一次移動一個位置,當兩個指針再次相遇時,指針所指的節點即入口節點。 之所以這樣能夠定位環的入口節點,原因解析如下: 假設鏈表頭節點爲head,環入口節點爲entrance,並假設有head到entrance共有n個節點(包括head, 但不包括entrance),環的節點個數爲m。我們知道,快指針和慢指針第一次相遇的節點肯定在環中, 假設從entrance到這個節點共k個節點(包括entrance和相遇的節點)。那麼此時slow指針共移動了 n+k 個節點,fast指針共移動了 2*(n+k) 個節點。則有 2*(n+k) = n + k + x*m,其中x 表示此時fast指針已經在環中繞的圈數。由此可以得到 n+k=x*m,即 n = (x-1)*m + m - k 。那麼此時再將慢指針重新指向head,並且slow指針和fast指針均以同樣的速度,每次移動一個節點 位置往後移動,那麼當slow指針走到entrance時,fast指針同樣移動到了entrance節點。 代碼如下: SListNode* FindBeginning(SListNode* head) { if (head == NULL) { return NULL; } SListNode* fast = head; SListNode* slow = head; while (1) { fast = fast->next->next; slow = slow->next; if (fast == slow) { break; } } slow = head; while (fast != slow) { fast = fast->next; slow = slow->next; } return fast; } 測試用例如下: void Test14() { SListNode *seq = NULL; PushBack(seq, 1); PushBack(seq, 2); PushBack(seq, 3); PushBack(seq, 4); PushBack(seq, 5); PushBack(seq, 6); PushBack(seq, 7); PushBack(seq, 8); PushBack(seq, 9); PushBack(seq, 10); SListNode * address1 = Find(seq, 10); //將節點10的地址返回給address1 SListNode * address2 = Find(seq, 6); //將節點6的地址返回給address2 address1->next = address2; //節點10就會指向節點6,這樣就形成一個環 SListNode* ret=FindBeginning(seq); //利用函數返回環入口節點地址給ret cout << "入口節點是 "<<ret->date << endl; //輸出環入口節點的數據 } 運行結果如下:
求帶環的單鏈表入口位置處的節點
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.