[連結串列]leetcode23-合併 k 個升序連結串列
阿新 • • 發佈:2020-12-14
技術標籤:leetcode# leetcode-連結串列連結串列leetcode
[連結串列]–合併 k 個升序連結串列
題目連結
題目
給你一個連結串列陣列,每個連結串列都已經按升序排列。
請你將所有連結串列合併到一個升序連結串列中,返回合併後的連結串列。
示例
輸入:lists = [[1,4,5],[1,3,4],[2,6]] 輸出:[1,1,2,3,4,4,5,6] 解釋:連結串列陣列如下: [ 1->4->5, 1->3->4, 2->6 ] 將它們合併到一個有序連結串列中得到。 1->1->2->3->4->4->5->6
輸入:lists = []
輸出:[]
輸入:lists = [[]]
輸出:[]
解析
這個困難模式有點溼潤
leetcode 21.合併兩個有序連結串列 + 分治歸併
- 將 k 個連結串列兩兩一組合並,第一次完成之後變為(k/2)個連結串列。依次歸併…
- 重複上一步直至有序,也就是剩下一個連結串列
程式碼實現
public class Solution23 {
/**
* Definition for singly-linked list
*/
class ListNode {
int val;
ListNode next;
public ListNode(int val) {
this.val = val;
}
}
/**
* 使用分治 + 合併兩個有序連結串列
*/
public ListNode mergeKLists(ListNode[] lists) {
return merge(lists, 0, lists.length-1);
}
/**
* 歸併
*/
public ListNode merge(ListNode[] lists, int start, int end) {
if (start == end) return lists[start];
if (start > end) return null;
int mid = (start + end) / 2;
return mergeTwoLists(merge(lists, start, mid), merge(lists, mid+1, end));
}
/**
* 合併兩個有序連結串列
*/
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode newHead = new ListNode(0);
ListNode temp = newHead;
while (l1 != null && l2 != null) {
if (l1.val < l2.val) {
temp.next = l1;
temp = temp.next;
l1 = l1.next;
}else {
temp.next = l2;
temp = temp.next;
l2 = l2.next;
}
}
// 有一個連結串列遍歷完
temp.next = l1 != null ? l1 : l2;
return newHead.next;
}
}
發現了另一種比較有意思的:
- 定義傀儡頭結點用於連線新的合併連結串列;
- 將每個連結串列第一個節點都裝入優先順序佇列(小根堆),每次彈出一個節點之後將該節點所在連結串列的下一個節點(不為 null)放入優先順序佇列;
- 直到優先順序佇列為空。
程式碼實現
public class Solution23 {
/**
* Definition for singly-linked list
*/
class ListNode {
int val;
ListNode next;
public ListNode(int val) {
this.val = val;
}
}
/**
* 使用優先順序佇列
*/
public ListNode mergeKLists(ListNode[] lists) {
if (lists.length == 0) return null;
ListNode dummyHead = new ListNode(0);
ListNode temp = dummyHead;
// 優先順序佇列——小根堆
PriorityQueue<ListNode> queue = new PriorityQueue<>((o1, o2) -> o1.val-o2.val);
// 所有連結串列的第一個節點放入進行排序
for (int i = 0; i < lists.length; i++) {
if (lists[i] != null) {
queue.offer(lists[i]);
}
}
while (!queue.isEmpty()) {
ListNode next = queue.poll();// 確定彈出的節點是哪個連結串列的
temp.next = next;
temp = temp.next;
// 令彈出節點的連結串列的下一個節點進入佇列
if (next.next != null) {
queue.offer(next.next);
}
}
return dummyHead.next;
}
}
-----------------------------------------------------------------------------有始有終分割線----------------------------------------------------------------------------------