概述:合併有序鏈表的一種實現
在Leetcode刷題的時候,碰到有序鏈表的合併問題,第21題是兩個鏈表的合併,第23提是k個鏈表的合併,第23題利用第21題的解法,將兩個鏈表合成一個,再把合成的鏈表作爲新鏈表和下一個鏈表合併即可。合併鏈表有很多方法:
a.將所有節點拆開,放到數組裏進行排序,再放回鏈表,這種方法實現最簡單,但是放棄了鏈表本身插入刪除成本低的優勢;
b.另一種方法是分別遍歷兩個鏈表,將節點從小到大一次加到另外一個新鏈表中,這種方法也比較簡單,定義兩個指針分別遍歷就好;
c.第三種方法是遍歷其中一張表,將節點數據插入到另一張鏈表對應的節點,這種方法的思路也簡單,很容易想到,但是實現起來會有一些坑,沒有IDE的情況下調試起來還是不太直觀的,其中需要特別注意的是頭插和尾插的處理。
代碼如下:
public class T23 {
/**
* 合併k個有序鏈表
* @param lists 待合併的鏈表的數組
* @return 合併後的有序鏈表第一個節點
*/
public ListNode mergeKLists(ListNode[] lists) {
ListNode p = null;
for(ListNode node : lists){
p = mergeTwoLists(p,node);
}
return p;
}
/**
* 合併兩個有序鏈表
* @param p 有序鏈表1
* @param node 有序鏈表2
* @return 鏈表2插入到鏈表1的合併結果
*/
public static ListNode mergeTwoLists(ListNode p, ListNode node) {
if (p == null) {
return node;
}
if (node == null) {
return p;
}
ListNode pFirst = p;
ListNode prep = p;
ListNode curNode = node;
while (curNode != null) {
node = node.next;
while (p != null) {
if (p.val < curNode.val) {
prep = p;
p = p.next;
} else if (prep != p) {
curNode.next = prep.next;
prep.next = curNode;
break;
} else {
break;
}
}
// prep == p 說明在第一個節點之前插入
if (prep == p) {
curNode.next = prep;
pFirst = curNode;
}
// p == null 說明在末尾插入
if (p == null) {
prep.next = curNode;
curNode.next = null;
}
curNode = node;
p = pFirst;
prep = p;
}
return pFirst;
}
}
class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
}
}