23. 合并K个升序链表

385 阅读1分钟

题目描述

给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。

示例

示例 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)
链接:leetcode-cn.com/problems/me…

分析

根据题意发现与21. 合并两个有序链表非常相似,只不过把2个换成K个,那么我们就考虑是否可以将K个转换成2个呢,很自然的想到用归并,递归的将K个链表转换为多个2个链表的形式,因此我们的思路如下:递归地拆分数组链表,两两合并

实现

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
// 两个链表合并
struct ListNode *mergeTwoKLists(struct ListNode *left, struct ListNode *right)
{
    if (!left) {
        return right;
    }
    if (!right) {
        return left;
    }
    struct ListNode *head = (struct ListNode *)malloc(sizeof(struct ListNode));
    head->val = 0;
    head->next = left;
    struct ListNode *p = head;
    while (left && right) {
        if (left->val > right->val) {
            p->next = right;
            right = right->next;
        } else {
            p->next = left;
            left = left->next;
        }
        p = p->next;
    }
    if (left) {
        p->next = left;
    }
    if (right) {
        p->next = right;
    }
    return head->next;
}

struct ListNode *mergeKLists(struct ListNode **lists, int listsSize)
{
    if (listsSize == 0) {
        return NULL;
    }
    if (listsSize == 1) {
        return lists[0];
    }
    if (listsSize == 2) {
        return mergeTwoKLists(lists[0], lists[1]);
    }
    
    // 归并
    struct ListNode *left = mergeKLists(&lists[0], listsSize / 2);
    struct ListNode *right = mergeKLists(&lists[listsSize/2], listsSize - listsSize / 2);
    return mergeTwoKLists(left, right);
}