力扣 23. 合并K个排序链表 链表+归并+优先队列

181 篇文章 1 订阅
38 篇文章 0 订阅

https://leetcode-cn.com/problems/merge-k-sorted-lists/
在这里插入图片描述

思路一:暴力合并,即利用 m e r g e merge merge算法,逐一合并两个链表。为方便分析复杂度,我们假设有 k k k个链表,每个链表的最大长度为 n n n,那么该算法的时间复杂度为 O ( n ∗ k 2 ) O(n*k^2) O(nk2)

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    //合并两个有序链表
    ListNode* merge(ListNode* l,ListNode* r){
        ListNode head(0),*cur=&head;
        while(l&&r){
            if(l->val<=r->val)
                cur->next=l,cur=l,l=l->next;
            else
                cur->next=r,cur=r,r=r->next;
        }
        cur->next=l?l:r;
        return head.next;
    }
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        int siz=lists.size();
        if(!siz)
            return nullptr;
        ListNode *ans=lists[0];
        for(int i=1;i<siz;i++)
            ans=merge(ans,lists[i]);
        return ans;
    }
};

思路二:归并合并链表,即首先两个两个合并构成新的一层链表,然后再两个两个合并……时间复杂度为 O ( k l o g k ∗ n ) O(klogk*n) O(klogkn)

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    //合并两个有序链表
    ListNode* merge(ListNode* l,ListNode* r){
        ListNode head(0),*cur=&head;
        while(l&&r){
            if(l->val<=r->val)
                cur->next=l,cur=l,l=l->next;
            else
                cur->next=r,cur=r,r=r->next;
        }
        cur->next=l?l:r;
        return head.next;
    }
    ListNode* mergeLists(vector<ListNode*>& list,int l,int r){
        if(l==r)
            return nullptr;
        if(l+1==r)
            return list[l];
        int mid=(l+r)>>1;
        return merge(mergeLists(list,l,mid),mergeLists(list,mid,r));
    }
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        int siz=lists.size();
        if(!siz)
            return nullptr;
        return mergeLists(lists,0,siz);
    }
};

思路三:利用优先队列。考虑一次合并 k k k个链表,那么我们肯定想获得这 k k k个节点中最小的那个节点的值,套个优先队列就行了。时间复杂度也是 O ( k l o g k ∗ n ) O(klogk*n) O(klogkn)

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    bool cmp(ListNode *&a,ListNode *&b){
        return a->val<b->val;
    }
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        int siz=lists.size();
        if(!siz)
            return nullptr;
        auto cmp=[](ListNode *&a,ListNode *&b){ return a->val>b->val; };
        priority_queue<ListNode*,vector<ListNode*>,decltype(cmp)> q(cmp);
        for(int i=0;i<siz;i++){
            if(lists[i])
                q.push(lists[i]);
        }
        ListNode head(0),*cur=&head,*tmp;
        while(!q.empty()){
            tmp=q.top();
            q.pop();
            cur->next=tmp;
            cur=tmp;
            tmp=tmp->next;
            if(tmp)
                q.push(tmp);
        }
        return head.next;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值