力扣023 合并k个排序列表
力扣023 合并k个排序列表
题目:
给你一个链表数组,每个链表按升序排序。k``lists
将所有链接列表合并为一个排序的链接列表并返回它。
示例 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
示例 2:
Input: lists = []
Output: []
示例3:
Input: lists = [[]]
Output: []
约束:
k == lists.length
0 <= k <= 104
0 <= lists[i].length <= 500
-104 <= lists[i][j] <= 104
lists[i]
按升序排序。- 的总和不会超过 。
lists[i].length``104
解题思路:
首先我们想到要将k个有序链表合并成为一个有序链表,肯定会涉及到链表节点之间的比较。所以我们首先定义一个比较器用来比较链表节点之间的大小其次我们用到一个优先队列第一次先将每个链表的头节点放入优先队列中然后每次从这个优先队列中取出一个元素就判断这个节点的后面是否还存在节点如果存在节点就将它的下一个节点又放入到优先队列中,始终秉持“取出一个元素加入一个元素”,直到这个优先队列为空。并依次将取出的元素串联起来形成一个新的链表最后返回这个新链表的头部。
代码:
import java.util.Comparator;
import java.util.PriorityQueue;
/**
* 给一个链表数组,每个链表都是升序有序排列,请你将所有链表合并到一个有序的升序的链表中并返回合并后的链表
*/
public class MergeAscLists {
//1.首先定义一个节点类
public static class ListNode{
public int value;
public ListNode next;
public ListNode(int value) {
this.value = value;
}
}
//2.再自己定义一个比较器
public static class ListNodeComparator implements Comparator<ListNode>{
/**
* 重写比较的方法:
* 所有的比较方法如果返回的是负数那么第一个参数o1在前面第二个参数o2在后面
* 如果返回的是正数那么第二个参数o2在前面第一个参数o1的后面
* 如果返回的是0那么第一个参数和第二个参数相等
* @param o1
* @param o2
* @return
*/
@Override
public int compare(ListNode o1, ListNode o2) {
return o1.value - o2.value;
}
}
//3.合并多个有序链表,参数为一个节点数组每个节点表示一个链表的头节点代表一个链表
public static ListNode mergeLists(ListNode[] lists){
//3.1如果数组为空返回null
if (lists == null) {
return null;
}
//3.2定义一个优先队列(其实这个优先队列是一个小根堆)
PriorityQueue<ListNode> heap = new PriorityQueue<>(new ListNodeComparator());
//3.3首先我们先将每个链表的头节点放进这个优先队列heap
for (int i = 0; i < lists.length; i++) {
if (lists[i] != null){
heap.add(lists[i]);
}
}
//3.3.1如果这个优先队列heap为空则返回null
if(heap.isEmpty()){
return null;
}
//3.3.2定义一个变量为head,head指向优先队列取出的元素 也就是先弹出一个作为整体的头部 先抓住最后返回
ListNode head = heap.poll();
//3.3.3定义一个变量pre指向head
ListNode pre = head;
/*
4.判断pre后面还有没有节点(因为刚开始lists数组中每个元素代表的是每个链表的头节点
所以这个操作就是判断链表后面还有没有节点如果有就将它加入到优先队列中)
*/
if (pre.next != null){
heap.add(pre.next);
}
//5.依次从这个优先队列heap中取出元素,每弹出一个就挂在head的next指针上
while (!heap.isEmpty()){
//5.1弹出一个元素
ListNode cur = heap.poll();
//5.2将弹出的这个元素挂在head的next指针上因为pre指向head
pre.next = cur;
//5.3然后pre继续往下走 指向现在的cur
pre = cur;
//5.4如果当前的cur的next指针不为空就将它加入到优先队列heap中
if(cur.next != null){
heap.add(cur.next);
}
}
/*
总结:也就是出来一个进去一个出来一个进去一个直到这个优先队列为空的时候
*/
//6.最后返回第一次抓住的head这就是合并后的链表的头节点
return head;
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧