leetcode刷题之合并K个排序链表

题目

合并K个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
示例:

输入:
[
  1->4->5,
  1->3->4,
  2->6
]
输出: 1->1->2->3->4->4->5->6

解答思路

这是我在QQ群看到别人刷到这题,他说这题和算法导论里面的习题6.9一模一样。我特意去算法导论里面找,然后看到了这题:
在这里插入图片描述惭愧,我之前看算法导论的时候就没做后面的习题,这题居然在leetcode标为困难。所有我利用最小优先队列来做这道题。
解题思路:将K个排序链表的第一个结点构建小顶堆,这样确保每次取K个链表中最小的结点时间复杂度为常数1,每次取一个结点,该结点之后的结点填充该结点位置,然后维护堆的性质,维护堆的性质时间复杂度为log(k),取完一条链表之后,堆长度减一,维护堆的性质。这样总共需要取n个结点,每次取结点的时间复杂度为1,每次取完都要维护堆的性质,维护堆的时间复杂度为log(k),所以总的时间复杂度为nlog(k)。
如果你用暴力求解,每次遍历K个链表取最小的出来,那么时间复杂度为n*k。

C++代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:

int getParent(int i) { return i == 0 ? i : (i - 1) >> 1; }
    int getleft(int i) { return ((i + 1) << 1) - 1; }
    int getright(int i) { return (i + 1) << 1; }
    void fixupHeap(vector<ListNode*>& lists, int i, int heapSize) {
        if (i >= heapSize) { return; }
        int min = i;
        if (getleft(i) < heapSize && lists.at(min)!=0 && lists.at(getleft(i))!=0 &&lists.at(min)->val > lists.at(getleft(i))->val  ) {
            //swap(lists.at(i), lists.at(getleft(i)));
            min = getleft(i);
        }
        if (getright(i) < heapSize && lists.at(min)!=0 && lists.at(getright(i))!=0 && lists.at(min)->val > lists.at(getright(i))->val  ) {
            //swap(lists.at(i), lists.at(getright(i)));
            min = getright(i);
        }
        if (min != i) {
            swap(lists.at(i), lists.at(min));
            fixupHeap(lists, min, heapSize);
        }
    }
    void buildHeap(vector<ListNode*>& lists,int* heapSize) {
        for (int i = 0; i < (*heapSize); i++)
        {
            if (lists.at(i) == 0) {
                swap(lists.at(i), lists.at((*heapSize) - 1));
                --(*heapSize);
                --i;
            }
        }
        for (int i = lists.size() / 2; i >= 0; i--) {
            fixupHeap(lists, i, lists.size());
        }
    }
    ListNode* ExcMin(vector<ListNode*>& lists, int* heapSize) {
        ListNode* res = 0;
        if ((*heapSize) < 1) { return res; }
        else if ((*heapSize) == 1) {
            res = lists.at(0);
            if(lists.at(0)->next == 0){
                --(*heapSize);
            }else{
                lists.at(0) = lists.at(0)->next;
            }
            return res;
        }
        else {
            res = lists.at(0);
            if (lists.at(0)->next != 0) {
                lists.at(0) = lists.at(0)->next;
            }
            else {
                swap(lists.at(0), lists.at((*heapSize)-1));
                --(*heapSize);
            }
            fixupHeap(lists, 0, *heapSize);
        }
        return res;
    }
    ListNode* GetMin(vector<ListNode*>& lists, int* heapSize) {
        ListNode* res = 0;
        if ((*heapSize) < 1) { return res; }
        else {
            res = lists.at(0);
            return res;
        }
    }
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        
        int size = lists.size();
        int* heapSize = &size;
        buildHeap(lists,heapSize);//创建小顶堆
        ListNode* p = ExcMin(lists, heapSize);
        ListNode* root = p;
        while (GetMin(lists, heapSize) != 0) {
            ListNode* q = ExcMin(lists, heapSize);
            p->next = q;
            p = q;
        }
        if(p != 0){
            p->next = 0;
        }
        

        return root;
    }
};

提交结果

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值