鍊錶中關於環的幾個小問題

2021-06-21 06:16:18 字數 1839 閱讀 1908

參考很多資料,也做了點題目,在這裡小彙總一下。有不到位的地方,懇請指出,謝謝!

描述:給定乙個煉表頭指標為head,針對這個鍊錶有如下問題:

1、如何判斷這個鍊錶有沒有環?

2、環的長度如何計算?

3、怎麼找到環開始的地方?

解決思路:

1、兩種思路,第一種:用乙個map儲存節點的位址,從前往後掃,如果某個節點的位址出現了兩次,則說明有環。這種思路實現起來也很快,但不適合解決第二個問題,空間複雜度比較大。在這裡不做主要討論。如果筆試或者面試碰到,一般考的是這裡的第二種方法。取兩個指標,slow和fast,開始都指向head,slow每次走一步,fast每次走兩步,如果這兩個指標最後能夠相遇,則說明有環。它的乙個簡單實現,參考:

2、兩個指標在環內相遇之後,再繼續走,到第二次再相遇,慢指標走了一圈,快指標走了兩圈,用乙個計數器記住慢指標的走的步數就可以得到環的長度。

3、如下圖:

slow和fast在p的位置相遇,這個時候slow走的距離 s = n + m2,fast走的距離為2s,因為二者相遇,肯定有fast在環內打轉,假設fast轉了n圈(其中n>=1),

所以就有 2s = n + n(m1 + m2) + m2;綜合這兩個等式,於是就有,n + m2 = n(m1 + m2),也就是n = (n-1)(m1+ m2) + m1

有了這個結論,讓slow和fast在p相遇之後,讓fast指向鍊錶開頭,從這個時候開始fast每次只走一步,slow繼續在環內走,還是一次一步,兩個指標再次相遇的地方就是環開始的地方,注意這個時候,slow在環內走了n-1圈。leetcode上有這個題目,參考:

乙個完整實現的**:

#include using namespace std;

struct listnode

;listnode *build_list_with_cycle(int a, int len, int begin) // begin為環開始的地方

if (i == begin)

q = tmp;

p->next = tmp;

p = p->next;

} p->next = q; // 最後乙個節點指標指向之前記錄的begin 的位置,讓鍊錶成環

return head;

}bool has_cycle(listnode *head)

return false;

}int cycle_length(listnode *head) // 在已經確定有環的情況下求環的長度

break;

} }return length;

}listnode *find_cycle_begin(listnode *head) //如果有環,返回環開始的地方,如果沒有,返回nullptr

return slow; // or return fast

} }return nullptr; // 找不到環,則返回空

}int main()

; int len = sizeof(a) / sizeof(int);

int begin;

cin >> begin;

listnode *head = build_list_with_cycle(a, len, begin);

listnode *cycle_begin = nullptr;

int pre_length;

if (has_cycle(head))

else

cout << "no cycle" << endl;

}

關於js中的幾個小問題。

問題1 使用連續賦值後面的變數會成為全域性物件的乙個屬性,並且這個屬性可以通過delete刪除。原因 賦值語句是從右往左執行的,我們將10賦值給了c,但是c此時還宣告,接著把c的返回值賦值給了b,但是b也還沒有宣告,最後賦值給了a此時a有宣告,所以a就是區域性變數。var a b c 10 cons...

關於面試的幾個小問題

回答樣本 如果是工作需要我會義不容辭加班,我現在單身,沒有任何家庭負擔,可以全身心的投入工作。但同時,我也會提高工作效率,減少不必要的加班。回答樣本一 我對工資沒有硬性要求,我相信貴公司在處理我的問題上會友善合理。我注重的是找對工作機會,所以只要條件公平,我則不會計較太多。回答樣本二 我受過系統的軟...

PHP中幾個小問題

1.定界符中的變數解析問題 data array name caihf province hubei echo 定界符在php手冊中的說明 另一種給字串定界的方法使用定界符語法 應該在 之後提供乙個識別符號,然後是字串,然後是同樣的識別符號結束字串。結束識別符號必須從行的第一列開始。同樣,識別符號也...