解題思路:
? ? ? ? 1.獲取信息:
? ? ? ? ? ? ? ? 給出了多個升序鏈表,要求合并成一個升序鏈表,返回首元結點
? ? ? ? 2.分析題目:
? ? ? ? ? ? ? ? 外面在21題的時候,講了怎樣合并兩個升序鏈表為一個升序鏈表,不了解的,建議去看一下21題題解,不要好高騖遠
? ? ? ? ? ? ? ? (有時候一個問題比較難,將它拆分成多個小問題取逐一解決是一個不錯的方法)
? ? ? ? ? ? ? ? 好了,那我們現在知道怎么合并兩個有序鏈表了,類比推理,我們可以將這個問題看作是兩數求和的那道題,我們怎么來選取鏈表進行合并,就顯得尤為重要
? ? ? ? ? ? ? ? (其實每道題的思路和想法都是融會貫通的,只要你理解了,學會了,都大差不差)
? ? ? ? ? ? ? ? 具體選取鏈表來合并的方式,我們在下面的嘗試編寫代碼環節中借著代碼,我會逐一講解
? ? ? ? 3.示例查驗:
? ? ? ? ? ? ? ? 示例1:說實話不夠鮮明,讓我感到鮮明的還是代碼框中給出的默認代碼
? ? ? ? ? ? ? ? 讓我知道,lists中是一個用來儲存首元結點地址的vector而已
? ? ? ? ? ? ? ? 示例2:如果lists為空,則返回空
? ? ? ? ? ? ? ? 示例3:如果lists中的鏈表為空,也返回空,因為空跟空合并也是空,但是如果空跟非空合并,那就是非空了
? ? ? ? 4.嘗試編寫代碼
? ? ? ? ? ? ? ? (1)逐次合并鏈表
? ? ? ? ? ? ? ? ? ? ? ? (在這里再說一下,我在這個貼子的題解中不會寫出怎么合并兩個有序鏈表,只會說怎么選取鏈表來合并,主要是最近我眼睛有點痛,不想看電子設備,等到康復的時候,我會補上的,還有就是可以幫助你,讓你多做一道題哦,就是21題,你可以開始感謝我了,注意:合并兩個有序鏈表可以用遞歸,也可以用迭代)
? ? ? ? ? ? ? ? ? ? ? ? 思路:取第一個鏈表和第二個鏈表進行合并,它們合并而成的鏈表再和第三個鏈表進行合并,依次類推,直到所有鏈表都進行了合并,成為了一個升序鏈表
以下是完整代碼
class Solution {
public:ListNode* mergeKLists(vector<ListNode*>& lists) {if(lists.empty())return nullptr;//如果lists為空,則返回空指針ListNode*dummy=lists[0];//取第一個鏈表for(int i=1;i<lists.size();i++){//依次取后續的鏈表dummy=Link(dummy,lists[i]);//這里自己品味一下}return dummy;//返回合并后的鏈表的首元結點的地址(也可以說指向首元結點的指針)}
private://這里還是照顧一下沒看過21題題解的。。。我想不出什么親切的稱呼,可以老少皆宜,可以自行腦補一下ListNode* Link(ListNode*dummy,ListNode*list){//這里我使用的遞歸來寫的合并兩個有序鏈表if(dummy==nullptr)return list;//如果某條鏈表為空,則返回沒空的那條鏈表if(list==nullptr)return dummy;if(dummy->val<list->val){dummy->next=Link(dummy->next,list);//比較小的那個結點的下一位是去掉比較小的那個結點的鏈表和另一條鏈表合并后的鏈表return dummy;}else{list->next=Link(dummy,list->next);return list;}}//我感覺我這里說的,你可能聽不懂,所以我還是建議你去看一下21題題解
};
? ? ? ? ? ? ? ? (2)分治法來合并鏈表
? ? ? ? ? ? ? ? ? ? ? ? 思路:分治法的思想就是大問題拆分成小問題
? ? ? ? ? ? ? ? ? ? ? ? 對于鏈表組lists,我們每次劃分為二,那么是不是最后可以劃成若干個只有兩個鏈表的組合,我們再合并這些組合,最后就是一個升序的鏈表了
文字無力,我還是放圖說話
以下是完整代碼(就不寫注釋了,自己品味,考驗一下你,測試一下你的忠誠度,后續眼睛不痛了,我會補上的)
class Solution {
public:ListNode* mergeKLists(vector<ListNode*>& lists) {if(lists.empty())return nullptr;return Sep(lists,0,lists.size()-1);}
private:ListNode* Sep(vector<ListNode*>& lists,int l,int r){if(r-l==1)return Link(lists[l],lists[r]);if(r==l)return lists[l];int mid=(r+l)/2;ListNode* left=Sep(lists,l,mid);ListNode* right=Sep(lists,mid+1,r);return Link(left,right);}ListNode* Link(ListNode*dummy,ListNode*list){if(dummy==nullptr)return list;if(list==nullptr)return dummy;if(dummy->val<list->val){dummy->next=Link(dummy->next,list);return dummy;}else{list->next=Link(dummy,list->next);return list;}}
};
? ? ? ? ? ? ? ? (3)選擇重造
? ? ? ? ? ? ? ? ? ? ? ? (這里留下這個在力扣上面看到的方法,我只給思路,后續眼睛不痛了,我會補上,還是老樣子,考驗一下你寫代碼的能力,你可以后續過來對答案,最遲后天就會補,畢竟是正事)
? ? ? ? ? ? ? ? ? ? ? ? 我們取每條鏈表的首元結點,在這么多個首元結點中,我們從小到大開始連接首元結點,連接完之后,我們再次取每條鏈表(每次取完首元結點,那些鏈表就失去了那些結點,原首元結點下一個結點就是新的首元結點)的首元結點,重復操作,直到每條鏈表都被取完了,那最后拼成的鏈表就是答案
? ? ? ? ? ? ? ? ? ? ? ? 好咯,接下來就交給你咯