LeetCode - Merge k Sorted Lists

本文介绍了两种解决合并K个已排序链表问题的方法:一种是分而治之的策略,通过递归合并两个链表直到只剩一个;另一种是利用优先队列(最小堆)进行节点的高效排序与合并。详细分析了每种方法的时间和空间复杂度。

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

https://leetcode.com/problems/merge-k-sorted-lists/

Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.

优快云坑爹博客,之前明明写过这篇,居然找不到了!

之前用JAVA写的代码,现在是用C++写的,JAVA的就不重写了。。。。代码跟这里差不多:

http://blog.youkuaiyun.com/linhuanmars/article/details/19899259

首先第一种方法是divide and conquer,就是先merge两个list,再依次往上。

假设每个链表最长长度为n,链表数为k,因此T(k) = 2*T(k/2) + O(nk), 因此时间复杂度是O(nk*logk),空间复杂度是递归栈的深度,O(logk)

class Solution {
public:
    ListNode *mergeKLists(vector<ListNode *> &lists) {
        return helper(lists, 0, lists.size()-1);
    }
    
    ListNode *helper(vector<ListNode *> &lists, int left, int right){
        if(left>right) return NULL;
        if(left==right) return lists[left];
        int mid = (left+right)/2;
        return merge(helper(lists, left, mid), helper(lists, mid+1, right));
    }
    ListNode *merge(ListNode* left, ListNode* right){
        ListNode* dummy = new ListNode(0);
        ListNode* trv = dummy;
        while(left!=NULL && right!=NULL){
            if(left->val < right->val){
                trv->next = left;
                left = left->next;
            }
            else{
                trv->next = right;
                right = right->next;
            }
            trv = trv->next;
        }
        if(left!=NULL) trv->next = left;
        else trv->next = right;
        ListNode * head = dummy->next;
        delete dummy;
        return head;
    }
};

另一种方式是使用priority queue,即min_heap来排序,先放k个node到min_heap里面去,再从heap中取出来最小的,再把最小的的下一个放到heap中去。

时间复杂度是O(nk*logk),因为入栈深度是logk,总共nk个节点。空间复杂度O(k),注意,写priority queue的时候一定要记得覆盖比较函数,另外需要注意的是,C++的每个类定义后面都有一个分号,一定不能忘了,而且C++空指针是NULL,JAVA是null,不要弄混了:

class Comparison{
    public:
    bool operator()(ListNode* n1, ListNode * n2){
        return n1->val > n2->val;
    }
};
class Solution {
public:
    ListNode *mergeKLists(vector<ListNode *> &lists) {
        priority_queue<ListNode *, vector<ListNode *>, Comparison> pq;
        for(int i=0; i<lists.size(); i++){
            if(lists[i] != NULL) pq.push(lists[i]);
        }
        ListNode *dummy = new ListNode(0);
        ListNode *trv = dummy;
        while(pq.size()>0){
            trv->next = pq.top();
            pq.pop();
            trv = trv->next;
            if(trv->next != NULL) pq.push(trv->next);
        }
        trv = dummy->next;
        delete dummy;
        return trv;
    }
};





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值