Time:2019/4/10
Title: Merge K Sorted Lists
Difficulty: Difficulty
Author: 小鹿
題目:Merge K Sorted Lists
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
合併 k 個排序連結串列,返回合併後的排序連結串列。請分析和描述演算法的複雜度。
Example:
Input:
[
1->4->5,
1->3->4,
2->6
]
Output: 1->1->2->3->4->4->5->6
複製程式碼
Solve:
▉ 演算法思路
如果我們完成了簡單的基於兩個單連結串列的合併之後,對於這個題來說,考察點是分治演算法,我認為還有一個考察點就是遞迴呼叫,分治的同時經常用遞迴來解決。
1、本道題可以藉助歸併排序的思想,稍加改造就可以解決。
2、將陣列中的連結串列分治,就是不斷的將陣列中的連結串列中間劃分,分別合併,然後整體合併成一個大連結串列。
▉ 程式碼實現
/**
* @param {number[]} nums
* @return {number[]}
* 功能:合併 k 個連結串列
* 邊界條件:
* 1)判斷陣列是否為空
* 2)判斷陣列長度為 1 時
* 3)判斷陣列長度為 2 時
* 4)判斷陣列長度大於 2 時
*/
var mergeKLists = function(lists) {
// 當 lists 中有一個連結串列時
if(lists.length == 0){
return null;
}else if(lists.length == 1){
// 判斷陣列長度為 1 時
return lists[0];
}else if(lists.length == 2){
// 判斷陣列長度為 2 時
return mergeTwoLists(lists[0],lists[1]);
}else{
// 判斷陣列長度大於 2 時
// 取陣列的中部座標
let middle = Math.floor(lists.length/2);
// 取左右兩邊陣列
let leftList = lists.slice(0,middle);
let rightList = lists.slice(middle);
// 遞迴、分割、合併
return mergeTwoLists(mergeKLists(leftList),mergeKLists(rightList));
}
};
//兩個連結串列合併
var mergeTwoLists = function(l1, l2) {
let result = null;
//終止條件
if(l1 == null) return l2;
if(l2 == null) return l1;
//判斷數值大小遞迴
if(l1.val < l2.val){
result = l1;
result.next = mergeTwoLists(l1.next,l2);
}else{
result = l2;
result.next = mergeTwoLists(l2.next,l1);
}
//返回結果
return result;
};
複製程式碼
▉ 擴充套件:分治演算法
分治演算法經常和遞迴一塊使用,所謂分治演算法,顧名思義,分而治之,最基本的分之演算法在歸併排序、快速排序都有用到。也就是將原問題劃分成 n 個規模較小,並且結構與原問題相似的子問題,遞迴地解決這些子問題,然後再合併其結果,就得到原問題的解。
1、分治演算法遞迴每層操作
- 分解:將原問題分解成一系列的子問題。
- 解決:遞迴地求解各個子問題,若子問題足夠小,則直接求解;
- 合併:將子問題的結果合併成原問題。
2、分治演算法滿足的條件
- 可分解:原問題與分解成的小問題具有相同的模式;
- 無關聯:原問題分解成的子問題可以獨立求解,子問題之間沒有相關性,這一點是分治演算法跟動態規劃的明顯區別。
- 終止條件:具有分解終止條件;
- 合併不能太複雜:可以將子問題合併成原問題,而這個合併操作的複雜度不能太高,否則就起不到減小演算法總體複雜度的效果了。
歡迎關注我個人公眾號:「一個不甘平凡的碼農」,記錄了自己一路自學程式設計的故事。
LeetCode 其他題目解析,Github:github.com/luxiangqian…