题目描述:
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
(合并k个有序链表).
思路:普通思路就是把每条链表单拿出来遍历,然后将链表中的元素一个一个往结果集中按大小放,直到所有链表都被遍历完。如果有n条链表,每个list的最大长度是m,假如使用,时间复杂度就是O((nm)^2).要是结果集使用堆结构,那么时间复杂度就是O(nmlognm).新思路就是纵向比较,假设总共有n个list,每个list的最大长度是m。构造一个大小为n的堆,每次取堆顶的最小元素放到结果集中,然后取该元素的下一个元素放入堆中,直到堆中无元素。因为每个每个元素要读取一次,为n*m次,然后每次将元素堆排序中要logn的复杂度,所以总时间复杂度是O(nmlogn)。
例如:
1->4->6
2->7->10
5->6->7
先比1,2,5,然后4,2,5,然后4,7,5,以此类推。
class ListNode
{
int val;
ListNode next;
ListNode(int x)
{
val = x;
}
}
public class Merge_k_Sorted_Lists {
public static ListNode mergeKLists(ListNode[] lists)
{
if(lists==null||lists.length==0)
return null;
//结果序列
ListNode result = null;
PriorityQueue<ListNode> heap = new PriorityQueue<ListNode>(new Comparator<ListNode>(){
@Override
public int compare(ListNode node1, ListNode node2) {
// TODO 自动生成的方法存根
return node1.val-node2.val;
}
});
for(int i=0;i<lists.length;i++)
{
if(lists[i]!=null)
//offer自动实现堆排序
heap.offer(lists[i]);
}
ListNode point = null;
while(heap.size()>0)
{
ListNode node = heap.poll();
if(result==null)
{
result = node;
point = result;
}
else
{
//将堆中最小的节点放入结果集
point.next = node;
}
//更新结果集指针后移
point = node;
//将出堆的节点的下一个节点放入堆中
if(node.next!=null)
{
heap.offer(node.next);
}
}
return result;
}
public static void main(String[] args) {
ListNode[] lists = {new ListNode(1),new ListNode(5),new ListNode(3),new ListNode(2),new ListNode(1)};
ListNode root = mergeKLists(lists);
while(root!=null)
{
System.out.println(root.val);
root = root.next;
}
}
}
在网上看见一个更好的办法: 思路是先分成两个子任务,然后递归求子任务,最后回溯回来。这个题目也是这样,先把k个list分成两半,然后继续划分,知道剩下两个list就合并起来,简单易于理解而且速度快。
class ListNode
{
int val;
ListNode next;
ListNode(int x)
{
val = x;
}
}
public class Merge_k_Sorted_Lists {
public static ListNode mergeTwoLists(ListNode l1, ListNode l2)
{
ListNode root = new ListNode(0);
ListNode point = root;
root.next = l1;
while(l1!=null&l2!=null)
{
if(l1.val>l2.val)
{
ListNode node = l2.next;
l2.next = point.next;
point.next = l2;
l2 = node;
}
else
{
l1 = l1.next;
}
point = point.next;
}
if(l2!=null)
{
point.next = l2;
}
return root.next;
}
public static ListNode solve(ListNode[] lists,int start,int last)
{
if(start>=last)
return lists[start];
int mid = (start+last)/2;
return mergeTwoLists(solve(lists,start,mid),solve(lists,mid+1,last));
}
public static ListNode mergeKLists(ListNode[] lists)
{
if(lists==null||lists.length==0)
return null;
return solve(lists,0,lists.length-1);
}
public static void main(String[] args) {
}
}