合并k个有序链表 leetcode23
联想
-
合并2个有序链表
-
8赛道跑马
思路1
- 维护一个大小为k的数字,存储链表头。
- 对链表头元素进行冒泡,得到最小的元素,取出,放到结果链表resList
- 将最小元素的后一个节点放入数组,重新冒泡一次,得到新的最小元素,放入resList。
- 重复第3步,若有链表排完了,置为null,放到数组末尾(可以维护一个数组的有效大小arrRealSize)
复杂度分析
- 时间复杂度
每次冒泡k,取出一个元素。一共n个元素,那么应该是O(nk)
- 空间复杂度
不考虑原始链表和结果链表,维护一个k的数组,应该是O(k)
思路2
对思路1稍稍改进
先进行一次排序O(klogk)
后续,只用对最小的元素的后续元素进行一次冒泡,那么平均复杂度可能大概是O(k/2)
O(k(logk+n/2))
public ListNode mergeKLists(ListNode[] lists) {
int arrRealLength = lists.length;
if (arrRealLength<=0) return null;
//检查一遍数组元素是否为null
for (int i = 0; i < arrRealLength; i++) {
if (lists[i]==null){
swap(lists,i,arrRealLength-- - 1);
i--;
}
}
for (int i = 0; i < arrRealLength; i++) {
bubbleSort(lists,0,arrRealLength-1-i,false);
}
if (lists[0]==null) return null;
//第1个元素,新链表的头
ListNode newHead = new ListNode(lists[0].val);
ListNode node = newHead;
lists[0] = lists[0].next;
if (lists[0]==null){
swap(lists,0,arrRealLength-- - 1);
}
while (arrRealLength>0){
bubbleSort(lists,0,arrRealLength-1,true);
node.next = lists[0];
node = node.next;
lists[0] = lists[0].next;
if (lists[0]==null){
swap(lists,0,arrRealLength-- - 1);
}
}
return newHead;
}
public void bubbleSort(ListNode[] lists,int start,int end,boolean isBreak){
for (int i = start; i <end ; i++) {
if (lists[i].val>lists[i+1].val){
swap(lists,i,i+1);
}else if (isBreak){
break;
}
}
}
public void swap(ListNode[] lists,int i,int j){
ListNode temp = lists[i];
lists[i]= lists[j];
lists[j] = temp;
}
leetcode结果:
554ms
41.6MB
思路3
以上冒泡过程其实只需要最小元素,那么可以用小顶堆来代替。
那也就是O(nlogk)
如果直接把所有元素放进小顶堆,再统一取出,也是O(nlogk)
但是空间复杂度上,前者O(k),后者O(n)
代码实现
public ListNode mergeKLists(ListNode[] lists){
PriorityQueue<ListNode> queue = new PriorityQueue<>(new Comparator<ListNode>() {
@Override
public int compare(ListNode o1, ListNode o2) {
return o1.val - o2.val;
}
});
for (int i = 0; i < lists.length; i++) {
if (lists[i]!=null) queue.offer(lists[i]);
}
ListNode newHead = new ListNode(-1);
ListNode node = newHead;
while (!queue.isEmpty()){
ListNode cur = queue.poll();
node.next = cur;
node = node.next;
if (cur.next!=null) queue.offer(cur.next);
}
return newHead.next;
}
leetcode结果:
5ms
41.6MB
分治(来自leetcode题解)
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
if (lists == null || lists.length == 0) return null;
return merge(lists, 0, lists.length - 1);
}
private ListNode merge(ListNode[] lists, int left, int right) {
if (left == right) return lists[left];
int mid = left + (right - left) / 2;
ListNode l1 = merge(lists, left, mid);
ListNode l2 = merge(lists, mid + 1, right);
return mergeTwoLists(l1, l2);
}
private ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if (l1 == null) return l2;
if (l2 == null) return l1;
if (l1.val < l2.val) {
l1.next = mergeTwoLists(l1.next, l2);
return l1;
} else {
l2.next = mergeTwoLists(l1,l2.next);
return l2;
}
}
}
作者:powcai
链接:https://leetcode-cn.com/problems/merge-k-sorted-lists/solution/leetcode-23-he-bing-kge-pai-xu-lian-biao-by-powcai/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
或许可以使用ForkJoinPool?(存疑)