Merge_k_Sorted_Lists

本文介绍了一种高效算法来合并多个有序链表,并详细解释了两种主要方法:一种利用优先队列实现,时间复杂度为O(nmlogn),另一种采用分治策略,通过递归合并两个链表,实现快速且简洁的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述:

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) {
		
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值