[LeetCode] 23. Merge k Sorted Lists
You are given an array of k
linked-lists lists
, each linked-list is sorted in ascending order.
Merge all the linked-lists into one sorted linked-list and return it.
Example 1:
Input: lists = [[1,4,5],[1,3,4],[2,6]] Output: [1,1,2,3,4,4,5,6] Explanation: The linked-lists are: [ 1->4->5, 1->3->4, 2->6 ] merging them into one sorted list: 1->1->2->3->4->4->5->6
Example 2:
Input: lists = [] Output: []
Example 3:
Input: lists = [[]] Output: []
Constraints:
k == lists.length
0 <= k <= 104
0 <= lists[i].length <= 500
-104 <= lists[i][j] <= 104
lists[i]
is sorted in ascending order.- The sum of
lists[i].length
will not exceed104
.
合并 K 个升序链表。
给你一个链表数组,每个链表都已经按升序排列。请你将所有链表合并到一个升序链表中,返回合并后的链表。
这道题有两种做法,时间空间复杂度一样,一个是用priority queue 解决,一个是用 merge sort 的思路解决。
首先是用 priority queue 的思路。因为JS实现 PQ 太过麻烦,所以 JS 实现我给出次优解,思路是 merge sort。
时间O(nlogk) - k 是链表的数量,最多有 k 个 node 在 pq 中,每次放一个新的 node 进去就要排序一次;所有的 node 都会被 pq 筛一遍,所以再乘以 n
空间O(n)
JavaScript实现
1 /** 2 * @param {ListNode[]} lists 3 * @return {ListNode} 4 */ 5 var mergeKLists = function (lists) { 6 return divide(lists, 0, lists.length - 1); 7 }; 8 9 var divide = function (lists, start, end) { 10 if (start === end) { 11 return lists[start]; 12 } else if (start < end) { 13 const mid = parseInt(start + (end - start) / 2); 14 const left = divide(lists, start, mid); 15 const right = divide(lists, mid + 1, end); 16 return merge(left, right); 17 } else { 18 return null; 19 } 20 } 21 22 var merge = function (left, right) { 23 if (!left) { 24 return right; 25 } else if (!right) { 26 return left; 27 } else if (left.val < right.val) { 28 left.next = merge(left.next, right); 29 return left; 30 } else { 31 right.next = merge(left, right.next); 32 return right; 33 } 34 }
Java实现 - priority queue
1 /** 2 * Definition for singly-linked list. 3 * public class ListNode { 4 * int val; 5 * ListNode next; 6 * ListNode() {} 7 * ListNode(int val) { this.val = val; } 8 * ListNode(int val, ListNode next) { this.val = val; this.next = next; } 9 * } 10 */ 11 class Solution { 12 public ListNode mergeKLists(ListNode[] lists) { 13 // corner case 14 if (lists == null || lists.length == 0) { 15 return null; 16 } 17 18 // normal case 19 PriorityQueue<ListNode> queue = new PriorityQueue<>(lists.length, (a, b) -> a.val - b.val); 20 ListNode dummy = new ListNode(0); 21 ListNode cur = dummy; 22 for (ListNode list : lists) { 23 // 注意sublist有可能是空的 24 if (list != null) { 25 queue.add(list); 26 } 27 } 28 29 while (!queue.isEmpty()) { 30 cur.next = queue.poll(); 31 cur = cur.next; 32 if (cur.next != null) { 33 queue.add(cur.next); 34 } 35 } 36 return dummy.next; 37 } 38 }
如下是Java实现的 merge sort 的思路。
1 /** 2 * Definition for singly-linked list. 3 * public class ListNode { 4 * int val; 5 * ListNode next; 6 * ListNode() {} 7 * ListNode(int val) { this.val = val; } 8 * ListNode(int val, ListNode next) { this.val = val; this.next = next; } 9 * } 10 */ 11 class Solution { 12 public ListNode mergeKLists(ListNode[] lists) { 13 // corner case 14 if (lists == null || lists.length == 0) { 15 return null; 16 } 17 return sort(lists, 0, lists.length - 1); 18 } 19 20 private ListNode sort(ListNode[] lists, int lo, int hi) { 21 if (lo >= hi) { 22 return lists[lo]; 23 } 24 int mid = lo + (hi - lo) / 2; 25 ListNode l1 = sort(lists, lo, mid); 26 ListNode l2 = sort(lists, mid + 1, hi); 27 return merge(l1, l2); 28 } 29 30 private ListNode merge(ListNode l1, ListNode l2) { 31 ListNode dummy = new ListNode(0); 32 ListNode cur = dummy; 33 while (l1 != null && l2 != null) { 34 if (l1.val < l2.val) { 35 cur.next = l1; 36 l1 = l1.next; 37 } else { 38 cur.next = l2; 39 l2 = l2.next; 40 } 41 cur = cur.next; 42 } 43 if (l1 == null) { 44 cur.next = l2; 45 } 46 if (l2 == null) { 47 cur.next = l1; 48 } 49 return dummy.next; 50 } 51 }
相关题目