本文主要總結鏈表算法中常用技術點
有序鏈表
1、合併有序鏈表
將兩個有序鏈表合併爲一個新的有序鏈表並返回,新鏈表是通過拼接給定的兩個鏈表的所有節點組成的。
見https://leetcode-cn.com/problems/merge-two-sorted-lists/
該算法主要就步驟是:
(1)確定鏈表頭結點
第一種方法可以判斷哪個鏈表頭大或者小,選擇其中一個座位頭結點;第二種方法是創建一個新節點,他的next指向頭結點
(2)選擇結點放在新鏈表中(升序爲例)
兩個指針分別指向兩個鏈表,一次比較兩個指針結點的值,將小的節點放在新鏈表後面,並將指向這個節點的指針後移
(3)將沒有遍歷完成的隊列放在新鏈表後面
2、鏈表排序
鏈表排序使用的是歸併排序,該算法主要步驟如下:
(1)找到中間位置
使用快慢指針的方法找到中間節點,注意快節點的初始值爲head->next,如果爲fast=head的時候 當只有兩個節點會出現無限循環( sortList)
(2)中間節點左右兩部分進行有序鏈表合併操作
return mergerList(sortList(head), sortList(fast));,該算法由於遞歸會最終遞歸到2個節點排序,4個節點排序,依次類推完全符合歸併排序的思路見(https://leetcode-cn.com/problems/sort-list/)
反轉鏈表
1、 反轉鏈表
反轉鏈表有兩種方法
(1)指針法
思路是不斷在老的鏈表中摘取節點,放在新鏈表的前面。
head指針指向新鏈表頭結點、q指針指向老鏈表的頭結點,r指向老鏈表頭結點的下一個節點
(2)棧結構
由於棧是先進後出,所以剛好滿足反轉,不過該方法的空間和時間複雜度高一些
2、 鏈表相加
鏈表相加就是數字相加,數據現加是從低位向高位進位,所以需要先把鏈表倒置,然後從前向後依次相加,注意進位;最終相加完再將鏈表倒置即可(https://leetcode-cn.com/problems/reverse-linked-list-ii/ https://leetcode-cn.com/problems/reverse-linked-list/)
3、 鏈表迴文
(1)後半部分倒轉
先使用快慢指針找到中間位置,找到以後將後半部分進行倒轉,倒轉以後跟前半部分一一對比即可
(2)前半部分倒轉
使用快慢指針找到中間部分,找的過程中用棧存儲慢指針數據,注意快指針最後是否爲空,不爲空說明爲奇數個節點,中間指針在向前移動一步,後半部分跟棧中數據進行比較即可
https://leetcode-cn.com/problems/palindrome-linked-list/
刪除鏈表
由於刪除數據可能會刪除頭結點數據,當刪除頭結點數據的時候不是很好操作,所以一般刪除操作都會引入輔助結點,創建一個新節點,該節點的next爲head,最後再刪除該節點即可
1、 刪除重複數據
鏈表中有重複的元素,刪除所有重複元素或者刪除重複元素使其不重複(https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list-ii/ https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list/)
2、刪除倒數第n個節點
兩個指針一個指向輔助節點,一個指向頭結點,然後先將指向頭結點向後移動n個節點
之後兩個指針同時向前移動,當指向頭結點的指針指向尾部NULL時,指向輔助節點的next剛好爲倒數第n個節點
3、 移除元素
沒有給定鏈表,僅僅是給定了鏈表中執行刪除的元素,並將該元素刪除,
void deleteNode(ListNode* node) {
ListNode* tmp=node->next;
node->val=tmp->val;
node->next=tmp->next;
delete(tmp);
}
相交鏈表
1、判斷鏈表是否有環,有環的話找到相交點
快慢指針相遇點到入環點的距離 = 頭結點到入環點的距離”:將頭結點到入環點的這一段環繞在環上,那麼快慢指針相遇點即爲出發點,即快慢指針相遇點到入環點的距離,等於頭結點到入環點的距離。 步驟一:判斷是否有環:快慢指針 步驟二:找出入環點:雙指針
ListNode *detectCycle(ListNode *head) {
if(head==NULL or head->next==NULL) return NULL;
ListNode* fast=head;
ListNode* slow=head;
while(fast!=NULL && fast->next!=NULL){
fast=fast->next->next;
slow=slow->next;
if(fast==slow ) {
slow=head;
while(slow!=fast){
slow=slow->next;
fast=fast->next;
}
return slow;
}
}
return NULL;
}
https://leetcode-cn.com/problems/linked-list-cycle-ii/
2、兩個鏈表相交,求相交點
這個是沒有環的相交,求該相交點的方式是:先得到兩個鏈表的長度,然後求出差值diff,長鏈表指針先走diff步,然後兩個鏈表指針一起走,兩個指針第一次相同的位置就是相交處
https://leetcode-cn.com/problems/intersection-of-two-linked-lists/
鏈表類型主要是這麼多,後續發現新題型在繼續添加