这是我参与11月更文挑战的第21天,活动详情查看:2021最后一次更文挑战
leetcode 合并K个升序链表
给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。
示例 1:
输入: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
示例 2:
输入:lists = []
输出:[]
示例 3:
输入:lists = [[]]
输出:[]
解题:一个链表数组内的链表都是升序的,要将他们合并成一个升序的链表,可以想办法每次获取一个数组内最小的链表节点,既然数组内链表是升序的,那么每次只用获取每个链表头结点,然后取出这些头节点中最小的一个节点,把这个最小节点拼接到结果链表中,最后取完所有节点时,结果链表就是最终合并的升序的链表了。首先创建一个节点值0的链表,一个指针指向这个链表,后面将获取到的最小节点利用指针拼接到这个节点后面,指针再往后移动一个节点,最后只需返回节点0后面的链表就行。由于不知道数组内有多少个节点,所以无法确定从数组取出最小节点的次数,所以先用while循环,然后用两个变量记录最小节点、和这个节点所在链表在数组内的索引,最小节点用于拼接到结果链表后面,这个索引用来去掉这个最小节点,最小节点取出后下次就不能用了,然后就循环数组内的链表,获取每个链表的头结点来和最小节点比较,最终保证取到最小的节点,但当数组内没有节点可取了,那就是合并完了,可以结束while循环,返回最终合并的结果链表即可。
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
ListNode resultListNode = new ListNode();
ListNode node = resultListNode;
// 每次获取一个最小节点 拼接到结果链表后
while (true) {
// 代表最小节点在数组的索引
int index = -1;
// 保存当前最小节点
ListNode minListNode = null;
// 遍历数组所有链表头结点查找出当前最小节点
for (int i = 0; i < lists.length; i++) {
ListNode listNode = lists[i];
// 如果当前数组内的链表不是空 那就获取节点值和已保存的最小节点值比较 保存两个中较小的节点
// 如果当前最小节点是空 说明是第一次 那就默认当前链表头结点最小
if (listNode != null && (minListNode == null || listNode.val < minListNode.val)) {
minListNode = listNode;
index = i;
}
}
// 都找不到最小节点了,就是找完了-结束
if (index == -1) {
break;
}
// 拼接上最小节点
node.next = minListNode;
node = node.next;
// 数组内链表后移一个
lists[index] = lists[index].next;
}
return resultListNode.next;
}
}
或者利用队列,将链表元素添加到排序的队列中,每次取出队列链表元素头结点就是最小节点,省去了比较获取最小节点步骤。
public ListNode mergeKLists(ListNode[] lists) {
// 创建自定义排序的队列
Queue<ListNode> queue = new PriorityQueue<>(new Comparator<ListNode>() {
@Override
public int compare(ListNode l1, ListNode l2) {
return l1.val - l2.val;
}
});
// 往队列添加元素
for (ListNode list : lists) {
if (list == null) {
continue;
}
queue.add(list);
}
ListNode resultListNode = new ListNode();
ListNode node = resultListNode;
// 取出队列最小节点拼接
while (!queue.isEmpty()) {
// 取出最小头节点
ListNode poll = queue.poll();
node.next = poll;
node = node.next;
// 再把后面节点加回去 如果有的话
if (poll.next != null) {
queue.add(poll.next);
}
}
return resultListNode.next;
}
或者类似于之前两个链表合并的操作,将k个链表拆分,两两合并最终也可以得到合并的升序链表。