Leetcode23:Merge k Sorted Lists
Posted 时不我待,只争朝夕
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Leetcode23:Merge k Sorted Lists相关的知识,希望对你有一定的参考价值。
Leetcode23:Merge k Sorted Lists
1. 题目描述
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
把K个已经排序的链表合并到一起并返回它的链表头,分析并描述它的复杂度。
2. 解题思路
这道题的难度是hard。这道题的解题思路有三种:
- 首先合并前两个链表得到一个链表,然后再和第三个合并,然后再和第四个合并,依次合并下去,直到最后得到一个链表。我们计算一下复杂度。
1、2合并,遍历2n个节点
1,2结果和3合并,遍历3n个节点
1,2,3结果和4合并,遍历4n个节点
1,2,3,..,k-1结果和k合并,遍历kn个节点
总共遍历的节点数目为n(2+3+…+k) = n*(k^2+k-2)/2, 因此时间复杂度是O(n*(k^2+k-2)/2) = O(nk^2)。
- 利用分治的思想,先把m个链表的合并分成m/2个双链表的合并,然后一次递减直到只有最后的一个或者两个链表。仔细想想这个过程是不是二分的逆过程。这个可以使用递归来实现,同样的思路在合并两个链表里也使用过。因此算法复杂度为T(k) = 2T(k/2) + O(nk),推导得到算法复杂度为O(nklogk)。
1、3合并,合并结果放到1的位置
2、4合并,合并结果放到2的位置
再把1、2合并(相当于原来的13 和 24合并)
- 维护一个k个大小的最小堆,初始化堆中元素为每个链表的头结点,每次从堆中选择最小的元素加入到结果链表,再选择该最小元素所在链表的下一个节点加入到堆中。这样当堆为空时,所有链表的节点都已经加入了结果链表。元素加入堆中的复杂度为O(longk),总共有kn个元素加入堆中,因此,复杂度也和算法2一样是O(nklogk)。
3.代码实现
- 依次合并
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
int n = lists.length;
if(n==0 || lists==null)
return null;
//if(n==1)
// return lists[0];
for(int i=1;i<n;i++) {
lists[0] = mergeTwoLists(lists[0],lists[i]);
}
n = k;
}
return lists[0];
}
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if(l1==null)
return l2;
if(l2==null)
return l1;
ListNode head = null;
ListNode head_c = l1.val>l2.val?l2:l1;
head = head_c;
while(l1 !=null && l2!=null) {
if(l1.val>l2.val) {
head.next = l2;
l2 = l2.next;
}
else {
head.next = l1;
l1 = l1.next;
}
}
if(l1==null) {
head.next = l2;
}
else {
head.next = l1;
}
return head_c.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 n = lists.length;
if(n==0 || lists==null)
return null;
//if(n==1)
// return lists[0];
while(n>1) {
int k = (n+1)/2;
for(int i=0;i<n/2;i++) {//注意这里i的取值范围,因为n存在奇偶两种情况
lists[i] = mergeTwoLists1(lists[i],lists[i+k]);
}
n = k;
}
return lists[0];
}
public ListNode mergeTwoLists1(ListNode l1, ListNode l2) {
if(l1==null)
return l2;
if(l2==null)
return l1;
if(l1.val<l2.val) {
l1.next = mergeTwoLists1(l1.next,l2);
return l1;
}else {
l2.next = mergeTwoLists1(l2.next,l1);
return l2;
}
}
}
- 维护最小堆
public class Solution {
public ListNode mergeKLists(List<ListNode> lists) {
if (lists==null||lists.size()==0) return null;
PriorityQueue<ListNode> queue= new PriorityQueue<ListNode>(lists.size(),new Comparator<ListNode>(){
@Override
public int compare(ListNode o1,ListNode o2){
if (o1.val<o2.val)
return -1;
else if (o1.val==o2.val)
return 0;
else
return 1;
}
});//建堆并重写compare函数
ListNode dummy = new ListNode(0);
ListNode tail=dummy;
for (ListNode node:lists)
if (node!=null)
queue.add(node);
while (!queue.isEmpty()){
tail.next=queue.poll();//取出堆中的最小值
tail=tail.next;
//并把所在链表的下一个放入堆中
if (tail.next!=null)
queue.add(tail.next);
}
return dummy.next;
}
}
以上是关于Leetcode23:Merge k Sorted Lists的主要内容,如果未能解决你的问题,请参考以下文章
[LeetCode] 23. Merge k Sorted Lists
leetcode23. Merge k Sorted Lists
leetCode 23. Merge k Sorted Lists
leetcode 23. Merge k Sorted Lists