雙指標技巧秒殺七道連結串列題目(1)
阿新 • • 發佈:2022-04-03
雙指標技巧秒殺七道連結串列題目
對於單鏈表相關的題目,雙指標的運用是非常廣泛的
例如:
1、合併兩個有序連結串列
2、合併 k
個有序連結串列
3、尋找單鏈表的倒數第 k
個節點
4、尋找單鏈表的中點
5、判斷單鏈表是否包含環並找出環起點
6、判斷兩個單鏈表是否相交併找出交點
合併兩個有序連結串列
最基本的連結串列技巧,力扣第 21 題「 合併兩個有序連結串列」
class Solution { public: ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) { // 虛擬頭結點 ListNode* dummy = new ListNode(-1); ListNode* p=dummy; ListNode* p1=list1; ListNode* p2=list2; while(p1!=nullptr&&p2!=nullptr){ if(p1->val>p2->val){ p->next=p2; p2=p2->next; }else{ p->next=p1; p1=p1->next; } p=p->next; } if(p1!=nullptr){ p->next=p1; } if(p2!=nullptr){ p->next=p2; } return dummy->next; } };
程式碼中還用到一個連結串列的演算法題中是很常見的「虛擬頭結點」技巧,也就是 dummy
節點。如果不使用 dummy
虛擬節點,程式碼會複雜很多,而有了 dummy
節點這個佔位符,可以避免處理空指標的情況,降低程式碼的複雜性。
合併 k 個有序連結串列
我的思路:讓連結串列兩兩合併,類似合併兩個連結串列。
class Solution { public: ListNode* mergeTwoLists(ListNode* p1,ListNode* p2){ if((!p1)||(!p2)) return p1?p1:p2; ListNode* dummy=new ListNode(); ListNode* p=dummy; ListNode* p3=p1; ListNode* p4=p2; while(p3!=nullptr&&p4!=nullptr){ if(p3->val>p4->val){ p->next=p4; p4=p4->next; }else{ p->next=p3; p3=p3->next; } p=p->next; } p->next=p3?p3:p4; return dummy->next; } ListNode* mergeKLists(vector<ListNode*>& lists) { ListNode* p=nullptr; for(int i=0;i<lists.size();i++){ p=mergeTwoLists(p,lists[i]); } return p; } };
但是這樣的時間複雜度與空間複雜度並不理想,因此可以考慮使用優先順序佇列(二叉堆)這種資料結構,把連結串列節點放入一個最小堆,就可以每次獲得 k
個節點中的最小節點
C++程式碼:
class Solution { public: ListNode* mergeKLists(vector<ListNode*>& lists) { //lambda //因為lambda的型別是由編譯器自動解析的,所以你不需要考慮像引數的型別是函式 指標或函式之類的事情。 //無論如何,decltype(...)都會解析為可呼叫的物件。 //lambda 二叉堆每次top放最小的 放進來的是b, auto compare=[](ListNode* a,ListNode* b){ return a->val>=b->val; }; //使用優先順序佇列(二叉堆)實現 priority_queue<ListNode*,vector<ListNode*>,decltype(compare)>pq(compare); //虛擬頭節點 ListNode* dummy=new ListNode(-1); ListNode* p=dummy; //將k個連結串列的頭節點加入最小堆 for(ListNode* head:lists){ if(head!=nullptr){ pq.push(head); } } while(!pq.empty()){ //獲得最小節點,接到結果連結串列中 ListNode* node=pq.top(); pq.pop(); p->next=node; if(node->next!=nullptr){ pq.push(node->next); } //p指標不斷前進 p=p->next; } return dummy->next; } };