点击关注公众号,干货第一时间送达

这是一道面试题,
在力扣上面有:

看到没,
"困难" 类型,
别慌,有小编在,
保证给你讲的明明白白
一、屏幕前的吴彦祖和刘亦菲们,请听题

举个例子:

能想到怎么求解吗?
二、解题
在合并K个链表之前,
诸位要先学会如何合并2个有序链表:

上面这两个 list,如何合并?
我们通过两个辅助指针 tmpA tmpB,分别执行两个链表头部,用于遍历:

再创建一个虚头节点,head,表示合并后的链表头部,通过 cur 辅助指针遍历。

然后开始遍历,
cur 需要拼接 tmpA 和 tmpB 中较小的,拼接完成,指针后移:

最后,返回头节点 head.next 即可。
以上是合并两个链表,
合并K个呢?
可以通过分治,即把k个链表,拆分成2份,4份...
合并后再合并即可。
看看代码。
完整代码:
public class CodingDemo_03 {
/**
* TODO: 合并K个有序链表
* @param lists
* @return
*/
private static ListNode mergeKLists(ListNode[] lists) {
if (lists == null){
return null;
}
return merge(lists, 0, lists.length-1);
}
//采用二分的方式,拆分链表数组中的链表,两两合并,最后再合并
private static ListNode merge(ListNode[] lists, int start, int end){
if (start == end){
return lists[start];
}
if (start > end){
return null;
}
int mid = (start+end)/2;
return mergeTwoList(merge(lists, start, mid), merge(lists, mid+1, end));
}
// 合并两个有序链表
private static ListNode mergeTwoList(ListNode listA, ListNode listB){
if (listA == null || listB == null){
return listA == null ? listB : listA;
}
//1,创建新头节点
ListNode head = new ListNode(0);
//辅助指针
ListNode cur = head;
//2,创建两个链表的辅助指针,用于遍历
ListNode tmpA = listA;
ListNode tmpB = listB;
//3,开始遍历,合并
while (tmpA != null && tmpB != null){
if (tmpA.val <= tmpB.val){
cur.next = tmpA;
//指针后移
tmpA = tmpA.next;
} else {
cur.next = tmpB;
//指针后移
tmpB = tmpB.next;
}
cur = cur.next; //移动
}
//4, 可能存在两个不一样长,需要拼接多出来的部分
cur.next = tmpA == null ? tmpB : tmpA;
return head.next;
}
private static class ListNode {
int val;
ListNode next;
ListNode() {
}
ListNode(int val) {
this.val = val;
}
ListNode(int val, ListNode next) {
this.val = val;
this.next = next;
}
}
}
去力扣试试:


文章转载自皮皮克克,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




