T23:合并k个升序链表
题目要求:
k 个已经排好序的链表
例如:
list1: 1 → 4 → 5
list2: 1 → 3 → 4
list3: 2 → 6
要求:
把它们合并成一个新的有序链表
最终结果:
1 → 1 → 2 → 3 → 4 → 4 → 5 → 6
题目核心:
如何把多个有序链表合并成一个有序链表?
核心思路(分治 / 归并)
像归并排序一样:
k个链表
↓
分成两半
↓
分别合并
↓
再合并结果
分治函数,合并链表代码实现
分治函数
java
private ListNode merge(ListNode[] lists, int left, int right){
if(left == right){
return lists[left];
}
int mid = (left + right) / 2;
ListNode l1 = merge(lists, left, mid);
ListNode l2 = merge(lists, mid + 1, right);
return mergeTwoLists(l1, l2);
}
逻辑:
递归拆分
直到只剩一个链表
再开始合并
合并两个链表
java
private ListNode mergeTwoLists(ListNode l1, ListNode l2){
ListNode dummy = new ListNode(0);
ListNode cur = dummy;
while(l1 != null && l2 != null){
if(l1.val < l2.val){
cur.next = l1;
l1 = l1.next;
}else{
cur.next = l2;
l2 = l2.next;
}
cur = cur.next;
}
if(l1 != null) cur.next = l1;
if(l2 != null) cur.next = l2;
return dummy.next;
}
代码实现
java
class Solution {
// 主函数:合并 k 个有序链表
public ListNode mergeKLists(ListNode[] lists) {
// 边界情况:如果数组为空,直接返回 null
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) / 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) {
// 创建虚拟头节点(方便操作)
ListNode dummy = new ListNode(0);
// cur 指针用于构建新链表
ListNode cur = dummy;
// 只要两个链表都没遍历完
while (l1 != null && l2 != null) {
// 谁小就接谁
if (l1.val < l2.val) {
cur.next = l1; // 接入 l1 节点
l1 = l1.next; // l1 指针后移
} else {
cur.next = l2; // 接入 l2 节点
l2 = l2.next; // l2 指针后移
}
// cur 指针前进
cur = cur.next;
}
// 如果 l1 还有剩余节点
if (l1 != null) {
cur.next = l1;
}
// 如果 l2 还有剩余节点
if (l2 != null) {
cur.next = l2;
}
// 返回合并后的链表头节点
return dummy.next;
}
}