• LeetCode #23 Merge k Sorted Lists k链归并 优先队列


    Description


      

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

    实现链表版的 k 路归并并分析其复杂度。

    思路


      一看到归并且要求时间复杂度尽可能低,那么自然联想到 T(n) = O(nlgn)  的归并排序或堆排序,但是代码都比较长些,短时间内不易解决。有没有什么简单快捷地办法呢?有的,那就是利用最小堆实现 k 路归并。先把 k 条链的元素全部入堆,每次取出堆顶元素,去掉原先的链,再重新链成一串即可。

      由于STL已经帮我们实现了优先队列,所以做题时直接使用 priority_queue 即可,它的模板声明带有三个参数, priority_queue<Type, Container, Functional> 其中 Type 为数据类型, Container 为保存数据的容器,Functional 为元素比较方式。主要方法有五个:push(), top(), pop(), size(), empty(),已经满足了本题需要的操作,入堆,取堆顶元素并出堆,查看当前堆的大小,堆是否为空。  

      此外还需要定义优先级,第一种方法是重载 () ,如下面的第一个例子。此时的 cmp 叫做仿函数/函数对象(functor),是指重载了operator()运算符的类,它广泛用于泛型编程。函数的形参形式最好写成 “const Type& a” 的形式,并且将该成员函数用 const 修饰。类似如下形式:

    struct cmp{
        bool operator () (const Type& a, const Type& b) const
        {
            return a.dat > b.dat;
        }
    };

    priority_queue<Type, Container, cmp> pQueue; 

      或者,在类中重载 < 操作符,并重载为友元函数

    struct T {
        Data dat;
        friend bool operator < (const Type& a, const Type& b)
        {
            return a.dat > b.dat;
        }
    };
    
    priority_queue<T> pQueue;

      

      扯远了,本题算法如下,由于每个元素入堆的时间是 O(lgn) ,需要线性扫描入堆也就是 O(nlgn),出堆时间是 O(lgn) ,串成链的时间是Θ(1),需要线性地让全部元素出堆也就是 O(nlgn),所以总时间 T(n) = O(nlgn) + O(nlgn) + n * Θ(1) = O(nlgn)

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    #include <iostream>
    #include <algorithm>
    
    struct cmp { 
        bool operator() (const ListNode* a, const ListNode* b) const
        {
            return (a->val > b->val);
        }
    };
    
    class Solution {
    public:
        ListNode* mergeKLists(vector<ListNode*>& lists) {
            priority_queue <ListNode*, vector<ListNode*>, cmp> pQueue;
            
            ListNode* lnode;
            for (auto c : lists) {
                lnode = c;
                while (lnode) {
                    pQueue.push (lnode);
                    lnode = lnode->next;
               }
            }
            
            if (pQueue.empty()) return NULL;
                
            ListNode *head, *p, *q;
            head = p = pQueue.top(); pQueue.pop();
            head->next =  p->next = NULL; //initialize first node of new linklist
            while (!pQueue.empty()) {           
                q = pQueue.top(); pQueue.pop();
                q->next = NULL; //broken pointer which was set previously
                p->next = q;
                p = q;
            }
            return head;
        }
    };
    View Code
    ————全心全意投入,拒绝画地为牢
  • 相关阅读:
    asp.net mvc 从数据库中读取图片
    给折腾ramdisk的朋友们一点建议
    docker安装Jenkins和构建python容器
    docker笔记
    接口加密方式
    Dockerfile常用命令
    北斗七星小队团队展示
    固件程序设计实验内容1.4
    Myod实验 20181328祝维卿
    电子公文系统团队作业(四):描述设计
  • 原文地址:https://www.cnblogs.com/Bw98blogs/p/8366075.html
Copyright © 2020-2023  润新知