雙指標技巧秒殺七道鍊錶題目(完

2022-10-09 11:57:11 字數 4154 閱讀 9644

從前往後尋找單鏈表的第k個節點很簡單,乙個 for 迴圈遍歷過去就找到了,但是如何尋找從後往前數的第k個節點呢?

這個解法就比較巧妙了,假設k = 2,思路如下:

首先,我們先讓乙個指標p1指向鍊錶的頭節點head,然後走k步:

現在的p1,只要再走n - k步,就能走到鍊錶末尾的空指標了對吧?

趁這個時候,再用乙個指標p2指向煉表頭節點head

接下來就很顯然了,讓p1p2同時向前走,p1走到鍊錶末尾的空指標時前進了n - k步,p2也從head開始前進了n - k步,停留在第n - k + 1個節點上,即恰好停煉表的倒數第k個節點上:

這樣,只遍歷了一次鍊錶,就獲得了倒數第k個節點p2

例如:力扣第 19 題「 刪除鍊錶的倒數第 n 個結點」

我的**:

class solution 

while(fast!=nullptr)

slow->next=slow->next->next;

return dummy->next;}};

注意:

​ 要使用虛擬頭節點,這樣可以省去討論許多特殊情況,返回dummy->next,head可以為空。

力扣第 876 題「 鍊錶的中間結點」就是這個題目,問題的關鍵也在於我們無法直接得到單鏈表的長度n,常規方法也是先遍歷鍊錶計算n,再遍歷一次得到第n / 2個節點,也就是中間節點。

我們讓兩個指標slowfast分別指向煉表頭結點head

每當慢指標slow前進一步,快指標fast就前進兩步,這樣,當fast走到鍊錶末尾時,slow就指向了鍊錶中點

我的**:

class solution 

}//只有乙個中間節點

return slow;}};

判斷鍊錶是否包含環屬於經典問題了,解決方案也是用快慢指標:

每當慢指標slow前進一步,快指標fast就前進兩步。

如果fast最終遇到空指標,說明鍊錶中沒有環;如果fast最終和slow相遇,那肯定是fast超過了slow一圈,說明鍊錶中含有環。

當然,這個問題還有高階版:如果鍊錶中含有環,如何計算這個環的起點?

可以看到,當快慢指標相遇時,讓其中任乙個指標指向頭節點,然後讓它倆以相同速度前進,再次相遇時所在的節點位置就是環開始的位置。

為什麼要這樣呢?這裡簡單說一下其中的原理。

我們假設快慢指標相遇時,慢指標slow走了k步,那麼快指標fast一定走了2k步:

fast一定比slow多走了k步,這多走的k步其實就是fast指標在環裡轉圈圈,所以k的值就是環長度的「整數倍」。

假設相遇點距環的起點的距離為m,那麼結合上圖的slow指標,環的起點距頭結點head的距離為k - m,也就是說如果從head前進k - m步就能到達環起點。

巧的是,如果從相遇點繼續前進k - m步,也恰好到達環起點。因為結合上圖的fast指標,從相遇點開始走k步可以轉回到相遇點,那走k - m步肯定就走到環起點了:

所以,只要我們把快慢指標中的任乙個重新指向head,然後兩個指標同速前進,k - m步後一定會相遇,相遇之處就是環的起點了。

力扣第 160 題「 相交鍊錶」

我的**:

class solution 

return a;}};

思路:

​ 本題書中思路比較清晰,無需總結

給你輸入兩個鍊錶的頭結點headaheadb,這兩個鍊錶可能存在相交。

如果相交,你的演算法應該返回相交的那個節點;如果沒相交,則返回 null。

比如題目給我們舉的例子,如果輸入的兩個鍊錶如下圖:

那麼我們的演算法應該返回c1這個節點。

這個題直接的想法可能是用hashset記錄乙個鍊錶的所有節點,然後和另一條鍊錶對比,但這就需要額外的空間。

如果不用額外的空間,只使用兩個指標,你如何做呢?

難點在於,由於兩條鍊錶的長度可能不同,兩條鍊錶之間的節點無法對應:

如果用兩個指標p1p2分別在兩條鍊錶上前進,並不能同時走到公共節點,也就無法得到相交節點c1

解決這個問題的關鍵是,通過某些方式,讓p1p2能夠同時到達相交節點c1

所以,我們可以讓p1遍歷完鍊錶a之後開始遍歷鍊錶b,讓p2遍歷完鍊錶b之後開始遍歷鍊錶a,這樣相當於「邏輯上」兩條鍊錶接在了一起。

如果這樣進行拼接,就可以讓p1p2同時進入公共部分,也就是同時到達相交節點c1

那你可能會問,如果說兩個鍊錶沒有相交點,是否能夠正確的返回 null 呢?

這個邏輯可以覆蓋這種情況的,相當於c1節點是 null 空指標嘛,可以正確返回 null。

按照這個思路,可以寫出如下**:

listnode getintersectionnode(listnode heada, listnode headb) 

return p1;

}

這樣,這道題就解決了,空間複雜度為o(1),時間複雜度為o(n)

鍊錶題目一道

原題鏈結 題意很簡單。給定乙個單鏈表,反轉這個單鏈表,返回翻轉後的頭節點。要將鍊錶翻轉,很容易想到借助棧的後進先出的性質來改變鍊錶的順序。將鍊錶節點順序壓入棧中,鍊錶節點全部進棧以後,取棧頂元素作為新鍊錶的頭節點,然後將元素不斷出棧,每齣棧乙個元素就連線到新鍊錶的末尾。時間複雜度 將鍊錶元素壓入棧中...

另一道鍊錶題目

有乙個鍊錶,它有next以及child屬性,每乙個child或者next指向的node也有相同的屬性,現在問如何遍歷所有的node。演算法有幾種option,第一種是用額外儲存空間,另一種是no extra memory。昨天和同事討論了一下,發現這道題目其實可以用遞迴來做,非常容易,幾句話就寫好了...

分隔鍊錶 雙指標操作

給定乙個鍊錶和乙個特定值 x,對鍊錶進行分隔,使得所有小於 x 的節點都在大於或等於 x 的節點之前。你應當保留兩個分割槽中每個節點的初始相對位置。輸入示例 head 1 4 3 2 5 2,x 3 輸出示例 1 2 2 4 3 5 c 結構體 definition for singly linke...