题目地址:合并K个升序链表
整体思路
无论有多少链表,因为每一个链表都是有序的,最小值必定在某一个链表的头。
可以使用PriorityQueue(优先队列)来进行解决,可以将每一个链表的头放到一个优先队列中,然后会弹出最小,这时,将弹出的那个头的下一个节点放入优先队列接着弹出,就是有一个有序链表生成
比较器
这时,创建优先队列就需要一个比较器
public static class listNodeCompaper implements Comparator<ListNode>{
@Override
public int compare(ListNode o1, ListNode o2) {
return o1.val-o2.val;
}
}
任何比较器都是返回负数代表o1在前,正数是o2在前,0则无所谓。这里直接两个Val一减其实比if判断要好的多。
边界判断
由于题中强调会出现传入null的情况
所以需要进行边界判断
if (lists == null) {
return null;
}
优先队列和核心循环
接着创建优先队列,把写的比较器塞进去
PriorityQueue<ListNode> heap = new PriorityQueue<>(new listNodeCompaper());
一个循环将{ListNode[] lists}的每一个节点传到优先队列里
for (int i = 0; i < lists.length; i++) {
if (lists[i] != null) {
heap.add(lists[i]);
}
}
由于这种情况,需要去判断一下优先队列中是否为空
接着就是先把最后要返回的最小头拿出来,再把下一个节点塞进去,再进行循环一直弹出,形成最后的一条链表
ListNode head = heap.poll();//要返回的最小头
ListNode pre = head;//临时变量的pre
if (pre.next != null ){
heap.add(pre.next);//如果不空就塞入下一个
}
while (!heap.isEmpty()) {
ListNode cur = heap.poll();//临时的cur,现在放的是下一个要弹出的节点
pre.next = cur;//将节点接上
pre = cur;//跳到出来的节点
if (cur.next != null) {
heap.add(cur.next);//如果不空就塞入下一个
}
}
下面是完整代码
public static class listNodeCompaper implements Comparator<ListNode>{
@Override
public int compare(ListNode o1, ListNode o2) {
return o1.val-o2.val;
}
}
public ListNode mergeKLists(ListNode[] lists) {
if (lists == null) {
return null;
}
PriorityQueue<ListNode> heap = new PriorityQueue<>(new listNodeCompaper());
for (int i = 0; i < lists.length; i++) {
if (lists[i] != null) {
heap.add(lists[i]);
}
}
if(heap.isEmpty()){
return null;
}
ListNode head = heap.poll();
ListNode pre = head;
if (pre.next != null ){
heap.add(pre.next);
}
while (!heap.isEmpty()) {
ListNode cur = heap.poll();
pre.next = cur;
pre = cur;
if (cur.next != null) {
heap.add(cur.next);
}
}
return head;
}