题目描述
合并K个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
示例1:
输入: lists = {listA, listB, listC}, listA= [1, 4, 5], listB = [1, 3, 4], listC = [2, 6]
输出: [1, 1, 2, 3, 4, 4, 5, 6]
思路分析
这道题目为困难难度,这道题和多路归并排序方法思路很像,核心思想是分而治之。我们在Leetcode21已知如何对两个排序链表进行合并,这里K个有序链表可通过两两合并的方式进行排序,这里我们给出示意图:
图1
如图1所示,我们在第一次两两排序时,间隔为1:{0,1; 2,3}
;第二次两两排序时,间隔为3:{0,3}
,易推断,间隔interval
初始值应为1
,之后更新为2 * interval, interval = interval*2
.
这里我们还需要注意,当输入的链表矩阵长度为奇数时,最后一项会在最终结果的前一次两两排序时参与到运算中。
解题步骤
- 初始化间隔整型变量
interval
,并求取输入矩阵长度len
; - 遍历链表矩阵,并在每次遍历后更新一对排序链表中的下表较小的链表指针,同时更新
interval = 2*interval
- 返回链表矩阵的首元素
lists[0]
解题代码
public static ListNode solution(ListNode[] lists) {
if(lists == null) return null;
if(lists.length == 1) return lists[0];
/* Step1: Init */
int interval = 1;
int len = lists.length;
/* Step2: go through the head-list
and
compare joint listnode in array-lists
*/
for (int i = 0; i < len; i = i + interval*2) {
for(int j = 0; j < len-interval; j=j+interval){
lists[j] = sortTwoSortedList(lists[j], lists[j + interval]);
}
interval *= 2;
}
return lists[0];
}
private static ListNode sortTwoSortedList(ListNode listA, ListNode listB) {
if (listA == null) {
return listB;
}
if (listB == null) {
return listA;
}
/* Step1: Init. pointers */
ListNode dummyHead = new ListNode(0);
ListNode pA = listA;
ListNode pB = listB;
ListNode tmpTail = dummyHead;
/* Step2: go through the head-list
and
compare pA.next.val and pB.val
*/
while (pA != null && pB != null) {
if (pA.val < pB.val) {
tmpTail.next = pA;
pA = pA.next;
} else {
tmpTail.next = pB;
pB = pB.next;
}
tmpTail = tmpTail.next;
}
// Step3: connect subsequent if exists
tmpTail.next = pA == null ? pB : pA;
/* Step4: return */
return dummyHead.next;
}
复杂度分析
已知链表矩阵的长度分别为k
(即链表个数),链表长度可设为N
:
时间复杂度:代码中我们存在for
循环的嵌套,且两两交换的时间复杂度为O(N);我们对链表矩阵进行了分治解法(第一层for
循环时间复杂度为O(logk)),故时间复杂度即为O(Nlogk)
;
空间复杂度:我们这里没有设置辅助容器,故空间复杂度为O(1)
.
GitHub源码
完整可运行文件请访问GitHub。