一、题目
题目链接:https://leetcode-cn.com/problems/merge-k-sorted-lists/
基础题目:合并两个升序列
题目链接:https://leetcode-cn.com/problems/merge-two-sorted-lists/submissions/
二、思路
思路一:
既然知道了合并两个升序列的方法,那多个升序列的话,只需分而治之,最终还是落到合并两个升序列上;
通俗的讲:每次都两两合并,一轮一轮下来,最终都会合成一条升序列
java代码实现:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
return mergeLists(lists, 0, lists.length - 1);
}
//分治合并list 递归
public ListNode mergeLists(ListNode[] lists, int start, int end) {
//递归终止条件
if (start == end) return lists[start];
if (start > end) return null;
int mid = (start + end)>>1;
return mergeTwoLists(mergeLists(lists, start, mid), mergeLists(lists, mid + 1, end));
}
//合并两个链表
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
if (list1 == null || list2 == null) {
return list1 == null ? list2 : list1;
}
ListNode head = new ListNode(0);
ListNode tail = head;
ListNode pre1 = list1;
ListNode pre2 = list2;
while (pre1 != null && pre2 != null) {
if(pre1.val > pre2.val) {
tail.next = pre2;
pre2 = pre2.next;
} else {
tail.next = pre1;
pre1 = pre1.next;
}
tail = tail.next;
}
tail.next = (pre1 == null ? pre2 : pre1);
return head.next;
}
}
思路二:
既然都是升序列,那每个链表第一个元素都是该链表最小的值,所以可以将k个链表的第一个元素都加入一个最小优先队列,
每次取队列里【最小的值】(也是当前所有链表中最小的值),然后将该【最小的值】所在的链表 当前最靠前的元素加入队列,又会进行升序排序
通俗的讲:每次比较 每个链表最小的值,得到全场最小的值;然后从最小值所在的链表中取该链表当前的最小值,补充进来,进行下一轮比较,以此类推,不断的得到全场最小值,不断的补充最小值进来;
java实现:
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
if (lists.length == 0) return null;
ListNode dummy = new ListNode(-1);
ListNode p = dummy;
// 优先级队列,最小堆
PriorityQueue<ListNode> pq = new PriorityQueue<>(
lists.length, (a, b)->(a.val - b.val));
// 将 k 个链表的头结点加入最小堆
for (ListNode head : lists) {
if (head != null)
pq.add(head);
}
while (!pq.isEmpty()) {
// 获取最小节点,接到结果链表中
ListNode node = pq.poll();
p.next = node;
if (node.next != null) {
pq.add(node.next);
}
// p 指针不断前进
p = p.next;
}
return dummy.next;
}
}