【链表】LeetCode 23.合并K个升序链表

26 阅读2分钟

困难

描述:

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

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

示例 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

思路:

根据前面的学过的知识“合并两个有序链表”不难想出:我们可以将数组里的链表进行两两合并,一直合并到只有一个数组,返回这个数组第一个元素即可。

代码示例(C++版)

class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        // 如果数组元素为空则直接返回空
        if(lists.size() == 0){
            return NULL;
        }
        // 如果数组元素只有1个则直接返回第一个元素
        if(lists.size() == 1){
            return lists[0];
        }
        // 只要数组元素大于1个就一直合并
        while(lists.size() > 1){
            // 创建临时数组,存放合并后的元素
            vector<ListNode*> tempList;
            // 开始合并
            for(int i = 0; i < lists.size(); i += 2){
                ListNode* l1 = lists[i];
                ListNode* l2 = NULL;
                if(i + 1 < lists.size()){
                    l2 = lists[i + 1];
                }
                // 添加到临时数组中
                tempList.push_back(mergeTwoLists(l1, l2));
            }
            // 将临时数组赋值给原数组
            lists = tempList;
        }
        return lists[0];
    }

    // 合并两个数组
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        // 创建哑节点(dummy node)
        ListNode* prehead = (ListNode*)malloc(sizeof(ListNode));
        prehead->val = -1;
        prehead->next = NULL;
        
        ListNode* prev = prehead;
        
        while (l1 != NULL && l2 != NULL) {
            if (l1->val <= l2->val) {
                prev->next = l1;
                l1 = l1->next;
            } else {
                prev->next = l2;
                l2 = l2->next;
            }
            prev = prev->next;
        }
        
        // 将剩余链表直接连接到末尾
        prev->next = (l1 == NULL) ? l2 : l1;
        
        ListNode* result = prehead->next;
        free(prehead); // 释放哑节点内存
        return result;
    }
};