1. 程式人生 > 其它 >資料結構與演算法(連結串列)

資料結構與演算法(連結串列)

資料結構與演算法(連結串列)

1,連結串列的資料結構

(1)基本實現(組成):由一個一個結點構成。

自己動手實現:定義了一個含有資料域 和 指標的 結點類。

(2)連結串列主要的功能(增刪改查):定義一些介面方法

(3)過程中進行重構連結串列,將 增刪改查 或者一些通用的介面或者屬性封裝到外部抽象類或者介面(方便設計給其他類用這樣子):

    

(整個版本一的連結串列過程如此)

過程中增刪改查實現的具體程式碼就 略。。。

增加:可以在任意一個位置進行增加結點

刪除:可以在任意一個位置進行刪除結點

修改:可以在任意一個位置進行修改結點

查詢:可以查詢任意一個位置的結點

✿ 升級版本

① 擁有虛擬頭結點的連結串列(統一了增加、刪除時接口裡的一些條件的判斷)

雙端(雙指標)連結串列(加快了查詢某個位置的結點~ 之前只能從頭到尾的遍歷,現在多了一個指標,便可以從尾到頭遍歷啦)

~~JDK1.8中的LinkedList中就是雙向連結串列(從原始碼分析得知的)

③ 迴圈連結串列(讓最後一個結點的指標指向了第一個結點)

④ 雙端迴圈連結串列(有兩個指標+ (最後一個結點的指標last 指向了第一個結點 、第一個結點的prev 指標指向最後一個結點))

2,連結串列的力扣演算法題:

總結一些小套路吧 (沒有通用的套路,就講一下方法哈)

自己需要先知道的是連結串列的特點就是一個一個結點構成(一般沒有特別強調的連結串列都是普通的連結串列(只有一個next 指標):找結點都是隻能從頭到尾去遍歷找它)

(1)138_複製帶隨機指標的連結串列 的方法 :

方法一:使用遞迴+ hashMap (因為隨機指標:一個節點可能被多個其他節點指向)
/** hashMpa 避免重複建立 **/
當我們拷貝節點時,「當前節點的隨機指標指向的節點」可能還沒建立,因此我們需要變換思路。一個可行方案是,我們利用回溯的方式,讓每個節點的拷貝操作相互獨立。

方法二:間隔插秧法啦(把秧苗插進來後,以前是走一步,現在多了一個結點要多走一步)
* 第一步:插入苗
* 第二步:先處理隨機指標的複製(原本有隨機、next的複製都需要處理?):優先處理隨機(之所以要把苗插入,就是為了實現在同一流水線具有同一規則,如果先處理next 導致已經變成兩條連結串列了,拿不到隨機了)

(2)141_環形連結串列 的方法與套路 :

方法一:使用 HashSet 實現不重複的新增 【Set 集合特點:不重複】

// HashSet 底層是HashMap(新增元素時會判斷是否已經存在,已經存在會新增不成功)

if (!visited.add(head)) {
return true;
}

套路一:快慢指標法 (生活常識:操場跑圈,跑得快的最終會追上跑得慢的)

(3)142_環形連結串列II 的方法與套路 :

方法一:【Set 集合特點:不重複】,通過 contains() 方法進行判斷

套路一:快慢指標法 [ 追上之後,通過將特殊位置點(起點、 交點、相遇點)~ 快慢指標之間的位移差距是兩倍--> 推匯出起點到交點 = 相遇點到交點]

(4)160_相交連結串列 的方法與套路 :

方法一:Set集合(裝入一條連結串列,然後以它為標準,依次拿另外一條連結串列的每個結點與它對比)

套路一:處理一下長度,使得兩條連結串列的長度相同後進行同步運動(相遇了即是交點)

(5)19_刪除連結串列的倒數第N個結點 的方法與套路 :

方法一:通過求總長len - N + 1 得到需要刪除連結串列的前一個結點

套路一:倒序~聯絡到棧(後進先出~倒序思維):通過棧(後進先出(pop掉 後面 第N個,從而可以拿到待刪除結點的前一個結點))

套路二:本質上是將倒數轉化成(兩個點之間)具體的距離,通過設定兩個距離是n 的指標(不斷的往後走,走到最後,差距便是倒數)~ 資料-->距離

(6)2_兩數相加 的套路 :

套路一 官網用 || 把連結串列是否為空的所有情況都考慮(加上利用題意:將空鏈的資料初始為 0, 過程是將兩條鏈的資料進行相加)

套路框架:

while (l1 != null || l2 != null){
if (l1 != null) {
l1 = l1.next;
}
if (l2 != null) {
l2 = l2.next;
}
}

(7)203_移除連結串列元素 的方法和套路 :

方法一:遞迴,在從第二個結點開始進行移除,最後考慮上第一個結點的情況

套路一:加上了一個虛擬頭結點後,拿自身結點的next 去 比較,一旦next 是待刪除目標結點,則自身便是那個待刪除結點的前一個結點

(8)206_反轉連結串列 的方法

方法一:遞迴

方法二:頭插法

(9)21_合併兩個有序連結串列 的方法 和 套路

方法一:遞迴(將第一條連結串列從第二個結點開始與 第二條連結串列進行比較,然後再處理第一條連結串列剩下的第一個結點的情況)

套路一:兩條鏈同時進行比較大小, 當其中一條連結串列資料到達了null,再處理剩下另外一條連結串列的資料

套路二:(6)官網用 || 把連結串列是否為空的所有情況都考慮(加上利用題意:將空鏈的資料初始為 0 )

(10)23_合併K個升序連結串列 的方法 和 套路:

方法一:暴力法(一條一條新增進來的合併法)

套路一:分治合併法 (將 k 條不斷地進行劃分成兩部分,直到 部分中的連結串列數量為 1,開始二合一)

套路二:優先佇列法(就是小根堆(具體程式碼就是 PriorityQueue類(長度,比較器))~從小到大排序:

每條連結串列會依據連結串列頭的大小順序進行排序~ 連結串列頭小的放入前面,大的放到後面(從小到大~ 內部自動排序哈哈哈)),

每次都彈出連結串列頭最小的連結串列(然後取走連結串列頭,又放回剩餘的連結串列(讓它根據剩餘連結串列的頭在queue 中進行排序))。

(11)24_兩兩交換連結串列中的節點 的方法 和 套路:

方法一:遞迴(根據題意,可以明白的是它是按照一對一對的結點進行交換位置的),遞迴先處理掉從第二對(第三個結點開始)到最後一對的情況,剩下前面一對(第一、二個結點)再進行處理。