https://leetcode-cn.com/problems/merge-k-sorted-lists/
这道题的前置题目是合并两个排序链表 https://leetcode-cn.com/problems/merge-two-sorted-lists/
- 暴力法
将所有链表合并后排序
时间复杂度O(NlogN) N= 总节点数量
空间复杂度O(N)
- 归并
基于合并两个排序链表,我们可以做到循环依次合并两个链表,将问题转换为合并两个排序链表k-1次;
由于每次合并前后,被合并链表和所得链表的结构(有序性)不变,因此可以采用分治、归并的方式,对每两个链表进行合并,再将合并后的结果继续按此逻辑每两个相合并
时间复杂度:O(NlogK)
举例图示:
0 1 2 3 4 5 6
01 23 45 6
0123 456
0123456
我的代码:
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ class Solution { public ListNode mergeKLists(ListNode[] lists) { if(lists.length == 1) return lists[0]; int distance = 1; int sumDistance = 0; ListNode head = null; while (condition(distance, lists.length)) { for (int i = 0; i < lists.length; i += (distance + 1 + sumDistance)) { if (i + distance < lists.length) { head = mergeTwoLists(lists[i], lists[i + distance]); lists[i] = head; } } sumDistance += distance; distance *= 2; } return head; } boolean condition(int distance, int length) { //distance = 最后一次合并结果 * 2 ,所以临界值判断需要除以2 //由于两两合并,所以一旦超过一半必然归并完成 return length % 2 == 0 ? (distance / 2) < length / 2 : (distance / 2) < (length + 1) / 2 ; } ListNode mergeTwoLists(ListNode l1, ListNode l2) { ListNode res = new ListNode(0); ListNode preHead = res; ListNode cur1 = l1; ListNode cur2 = l2; while (cur1 != null || cur2 != null) { if (cur1 != null && cur2 != null) { if (cur1.val > cur2.val) { res.next = new ListNode(cur2.val); cur2 = cur2.next; } else { res.next = new ListNode(cur1.val); cur1 = cur1.next; } } else if (cur1 == null && cur2 != null) { res.next = new ListNode(cur2.val); cur2 = cur2.next; } else if (cur2 == null && cur1 != null) { res.next = new ListNode(cur1.val); cur1 = cur1.next; } res = res.next; } return preHead.next; } }
改进思路:
由于我的实现需要计算每次合并的两个链表的下标,这个过程比较麻烦;看了其他解答后,发现这样一种解决方式
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ class Solution { public ListNode mergeKLists(ListNode[] lists) { int len = lists.length; if (len == 0) { return null; } // 将n个链表以中间为对称,合并,即合并 while(len>1) { for (int i=0; i<len/2; i++) { lists[i] = mergeTwoListsForK(lists[i], lists[len-1-i]); } len = (len+1)/2; } return lists[0]; } private ListNode mergeTwoListsForK(ListNode l1, ListNode l2) { ListNode head = new ListNode(-1); ListNode p = head; while(l1 != null && l2 != null) { if (l1.val < l2.val) { p.next = l1; l1 = l1.next; } else { p.next = l2; l2 = l2.next; } p = p.next; } if (l1 != null) { p.next = l1; } else if (l2 != null) { p.next = l2; } return head.next; } }
这个思路更方便解答,省却了计算偏移的过程
0 1 2 3 4 5 6
06 15 24 3
063 1524
0631524
来源:https://www.cnblogs.com/elinlinlinlog/p/12258335.html