Leetcode23. 合并K个升序链表

该博客讨论了如何高效地合并多个已排序的链表,提供了三种不同的方法:两两合并、分治法和使用优先队列。每种方法都分析了其时间复杂度,并给出了对应的代码实现。通过这些方法,可以将所有链表合并成一个单一的升序链表。

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

一、题目

给你一个链表数组,每个链表都已经按升序排列。

请你将所有链表合并到一个升序链表中,返回合并后的链表。

示例 1:
输入:lists = [[1,4,5],[1,3,4],[2,6]]
输出:[1,1,2,3,4,4,5,6]
解释:链表数组如下:
[
1->4->5,
1->3->4,
2->6
]
将它们合并到一个有序链表中得到。
1->1->2->3->4->4->5->6
示例 2:

输入:lists = []
输出:[]

示例 3:
输入:lists = [[]]
输出:[]

提示:

k == lists.length
0 <= k <= 10^4
0 <= lists[i].length <= 500
-10^4 <= lists[i][j] <= 10^4
lists[i] 按 升序 排列
lists[i].length 的总和不超过 10^4

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/merge-k-sorted-lists
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

二、代码实现

1)两两合并

在这里插入图片描述
如图所示,我把1、2合并,然后将合并的链表结果保存在2中,然后2、3合并···直到所有链表合并到一个链表中为止。

时间复杂度:设最常的链长为n,链有k个,第一次合并是需要O(2n),第二次是(3n),第n次则为O((k+1)n),则总时间复杂度为O(nk²)。

链表代码积累
cur=cur.next=listNodes[i];
bug积累
在最开始没有考虑特殊情况,需要加上if(lists==null||lists.length==0)return null;才能解决为空的情况

class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
    if(lists==null||lists.length==0)return null;
    for(int i=1;i<lists.length;i++) {
	mergeTwoLists(i,lists);
	}
	return lists[lists.length-1];
    }
    private static void mergeTwoLists(int i, ListNode[] listNodes) {
	// TODO Auto-generated method stub
	ListNode ans=new ListNode(-1);
	ListNode cur=ans;
	while(listNodes[i]!=null&&listNodes[i-1]!=null) {
	if(listNodes[i-1].val<=listNodes[i].val) {
		cur=cur.next=listNodes[i-1];
		listNodes[i-1]=listNodes[i-1].next;
	}
	else {
		cur=cur.next=listNodes[i];
		listNodes[i]=listNodes[i].next;
	}
	}
	cur=cur.next=listNodes[i-1]!=null?listNodes[i-1]:listNodes[i];
	listNodes[i]=ans.next;
}
}

2)分治法

在这里插入图片描述

假设有k条链,最长的链为n。则时间复杂度为O(knlogk)
1)需要if(l>r)return null;处理特殊情况
2)位运算的优先级小于算术运算,所以正确写法应该是int mid=l+((r-l)>>2);而不是int mid=l+(r-l)>>2;

class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        return merge(lists, 0, lists.length - 1);
    }

   private static ListNode merge(ListNode[] lists, int l, int r) {
			// TODO Auto-generated method stub
			if(l==r)return lists[l];
			//处理特殊情况
			if(l>r)return null;
			//位运算符一定要注意,优先级小于算术运算符
			int mid=l+((r-l)>>2);
			return mergeTwo(merge(lists,l,mid),merge(lists,mid+1,r));
		}
		private static ListNode mergeTwo(ListNode l1, ListNode l2) {
			// TODO Auto-generated method stub
		    ListNode head=new ListNode(-1);
		    ListNode cur=head;
		    while(l1!=null&&l2!=null) {
		    	if(l1.val<=l2.val) {
		    		cur=cur.next=l1;
		    		l1=l1.next;
		    	}
		    	else {
		    		cur=cur.next=l2;
		    		l2=l2.next;
		    	}
		    }
		    cur.next=l1!=null?l1:l2;
		    return head.next;
		}
}

3)优先队列

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值