算法題心得 - 鏈表

上篇文章介紹了數(shù)組,哈希表,字符串相關(guān)的算法,這篇文章介紹另一個(gè)重要的數(shù)據(jù)結(jié)構(gòu),鏈表

鏈表特點(diǎn)

鏈表,和數(shù)組相比較的話,對(duì)于存儲(chǔ)空間更加靈活,不像是數(shù)組,必須要求連續(xù)的空間,而且在數(shù)組中刪除一個(gè)元素,就比較麻煩了,嚴(yán)格而言,刪除數(shù)組中的一個(gè)元素,需要將后面的所有元素都向前移動(dòng)。但是數(shù)組這種數(shù)據(jù)結(jié)構(gòu)也有特別優(yōu)秀的特點(diǎn),就是查找的時(shí)間復(fù)雜度是O(1)。鏈表對(duì)存儲(chǔ)空間很靈活,不要求連續(xù),刪除一個(gè)節(jié)點(diǎn),只需要從整個(gè)鏈表中去掉就可以了。但是缺點(diǎn)就是查找的時(shí)間復(fù)雜度為O(n)。因此,究竟要用數(shù)組還是鏈表,要看項(xiàng)目的實(shí)際情況。

鏈表的節(jié)點(diǎn)可以理解為以下結(jié)構(gòu)

struct _Node;
typedef struct _Node {
struct _Node* next_;
} Node;

可以發(fā)現(xiàn),鏈表結(jié)構(gòu)體中有一個(gè)指向下一個(gè)節(jié)點(diǎn)的next_,這也就是鏈表成鏈的關(guān)鍵。因此鏈表很容易考察對(duì)指針的理解,而指針,也就是處理鏈表相關(guān)問(wèn)題的關(guān)鍵。

典型算法題

典型的算法題如面試題23:鏈表中環(huán)的入口節(jié)點(diǎn)

題目:如果一個(gè)鏈表中包含環(huán),如何找出環(huán)的入口節(jié)點(diǎn)?

這是一道典型的鏈表題。上面分析過(guò),解決鏈表類問(wèn)題,最關(guān)鍵的就在于指針。對(duì)于這類問(wèn)題,我們往往用兩個(gè)指針,這兩個(gè)指針可以從相同的節(jié)點(diǎn)出發(fā),也可以從不同的節(jié)點(diǎn)出發(fā),可以兩指針的速度相同,也可以速度不同,巧妙的運(yùn)用這些技巧,就可以解決一些復(fù)雜的問(wèn)題。

比如解決這個(gè)問(wèn)題,就需要類似的技巧。首先要對(duì)問(wèn)題進(jìn)行分解。對(duì)于復(fù)雜的問(wèn)題,我們要想辦法將其分解為簡(jiǎn)單的問(wèn)題。比如這個(gè)問(wèn)題,就可以做如下分解:如何判斷鏈表中有環(huán)?如果有環(huán)的話,如何得到鏈表中環(huán)的個(gè)數(shù)?最后就是如何找到環(huán)的入口點(diǎn)?

判斷鏈表成環(huán)

首先解決第一個(gè)問(wèn)題,就是如何判斷鏈表中有環(huán)。什么情況下有環(huán)呢?就是其中某一個(gè)節(jié)點(diǎn),他的下一個(gè)節(jié)點(diǎn)又指向了前面的節(jié)點(diǎn),如此一來(lái),這個(gè)鏈表,就永遠(yuǎn)找不到結(jié)尾了。就好像是一個(gè)跑道,一直在繞著圈跑,卻永遠(yuǎn)跑不到終點(diǎn)。有了這種啟發(fā),我們是不是可以判斷鏈表的next有沒(méi)有終止呢?如果從頭開(kāi)始遍歷節(jié)點(diǎn),如果某個(gè)節(jié)點(diǎn)的next_為nullptr,自然,就是沒(méi)有成環(huán)的鏈表。如果找不到next_為nullptr的節(jié)點(diǎn),則就是成環(huán)的鏈表。這是一個(gè)基本的思路,但是如果判斷的條件是

while (node_->next_ != nullptr) {
node_ = node_->next_;
}
// 如果代碼走到這里說(shuō)明沒(méi)有成環(huán)

這種判斷有一個(gè)致命的錯(cuò)誤,就是在成環(huán)的鏈表中,while的判斷條件永遠(yuǎn)是true的,因此這個(gè)while循環(huán)是退出不了的。這當(dāng)然是不可容忍的。如何讓while循環(huán)可以停止呢?也就是如何在成環(huán)的條件下找到停止的條件呢?這就需要用到剛才提到過(guò)的雙指針?lè)椒?。其?shí)思想非常簡(jiǎn)單,比如兩個(gè)人賽跑,如果跑的快的那個(gè)人追上跑的慢的人,則跑道肯定成環(huán)。有了這種思想,我們定義兩個(gè)指針,這兩個(gè)指針都從鏈表的head開(kāi)始跑,一個(gè)指針每次跑一個(gè)節(jié)點(diǎn),另一個(gè)指針每次跑兩個(gè)節(jié)點(diǎn),這就是兩個(gè)指針從相同的位置,但是速度不同的典型用法。如果一次跑兩個(gè)節(jié)點(diǎn)的那個(gè)指針,碰到了node_->next_ == nullptr的情況,則說(shuō)明鏈表不成環(huán)。如果一次跑兩個(gè)節(jié)點(diǎn)的那個(gè)指針,追上了一次跑一個(gè)的那個(gè)指針,則說(shuō)明鏈表成環(huán)。

確定鏈表環(huán)個(gè)數(shù)

下面我們來(lái)解決第二個(gè)問(wèn)題,就是得到鏈表環(huán)中的個(gè)數(shù)。有了上一步的結(jié)果,如果成環(huán)的話,快指針會(huì)追上慢指針。追上的那個(gè)節(jié)點(diǎn),肯定是環(huán)內(nèi)的某個(gè)節(jié)點(diǎn)。我們可以從這個(gè)節(jié)點(diǎn)開(kāi)始計(jì)數(shù),讓指針從這個(gè)節(jié)點(diǎn)開(kāi)始出發(fā),每次走一個(gè)節(jié)點(diǎn),沒(méi)走一個(gè)節(jié)點(diǎn),計(jì)數(shù)增加。由于這個(gè)指針是環(huán)內(nèi)的某個(gè)節(jié)點(diǎn),因此,這個(gè)指針一定會(huì)回到他出發(fā)的地方。當(dāng)他再次回到起始的節(jié)點(diǎn)時(shí),我們統(tǒng)計(jì)的計(jì)數(shù),就是環(huán)內(nèi)節(jié)點(diǎn)的個(gè)數(shù)。

確定鏈表環(huán)起始節(jié)點(diǎn)

有了前面的結(jié)論,我們已經(jīng)知道鏈表是否成環(huán),如果成環(huán)的話,環(huán)內(nèi)節(jié)點(diǎn)個(gè)數(shù)也清楚了?,F(xiàn)在讓我們找到環(huán)的起始節(jié)點(diǎn)。這里,我們還需要運(yùn)用雙指針的技巧,假設(shè)我們已經(jīng)知道了環(huán)內(nèi)的個(gè)數(shù)為k,我們可以定義兩個(gè)指針,其中一個(gè)指針從頭開(kāi)始出發(fā),另一個(gè)指針從第k個(gè)節(jié)點(diǎn)開(kāi)始出發(fā),兩個(gè)指針每次往前走一個(gè)節(jié)點(diǎn),當(dāng)兩個(gè)節(jié)點(diǎn)相遇的時(shí)候,就是環(huán)內(nèi)的第一個(gè)節(jié)點(diǎn)。

小結(jié)

從上面的典型面試題可以看出,解決鏈表類問(wèn)題,靈活的使用指針是關(guān)鍵,特別的,我們經(jīng)常會(huì)使用雙指針的技巧,兩個(gè)指針可以從同一個(gè)節(jié)點(diǎn)出發(fā),速度不同,也可以從不同的節(jié)點(diǎn)出發(fā),速度相同等等。靈活的使用這些技巧,可以解決一些復(fù)雜的鏈表問(wèn)題。特別的,對(duì)于任何復(fù)雜的問(wèn)題,我們都要將其積極的拆分為簡(jiǎn)單的問(wèn)題。這樣才能化繁為簡(jiǎn),一步一步的解決問(wèn)題。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • //leetcode中還有花樣鏈表題,這里幾個(gè)例子,冰山一角 求單鏈表中結(jié)點(diǎn)的個(gè)數(shù)----時(shí)間復(fù)雜度O(n)這是最...
    暗黑破壞球嘿哈閱讀 1,658評(píng)論 0 6
  • 搞懂單鏈表常見(jiàn)面試題 Hello 繼上次的 搞懂基本排序算法,這個(gè)一星期,我總結(jié)了,我所學(xué)習(xí)和思考的單鏈表基礎(chǔ)知識(shí)...
    醒著的碼者閱讀 4,734評(píng)論 1 45
  • 鏈表刪除[203] Remove Linked List Elements[19] Remove Nth Node...
    野狗子嗷嗷嗷閱讀 6,439評(píng)論 4 35
  • 我坐在電腦前,準(zhǔn)備瀏覽單位的網(wǎng)頁(yè),看看有沒(méi)有最新的消息,于是晃動(dòng)鼠標(biāo),喚醒屏幕,屏幕上出現(xiàn)了昨天打開(kāi)但還未瀏覽...
    守護(hù)的狗閱讀 179評(píng)論 0 1
  • 今日赴林州對(duì)農(nóng)村改革工作進(jìn)行調(diào)研,一路景致妖嬈,令人陶醉。大山巍峨,藍(lán)天如海,白云悠悠,秋色醉人。 ...
    太行客閱讀 494評(píng)論 0 0

友情鏈接更多精彩內(nèi)容