zoukankan      html  css  js  c++  java
  • LeetCode23 Merge k Sorted Lists

    题意:

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

    分析:

    方法1:

    利用做过的merge 2 sorted list,将头两个归并,结果再与下一个归并,以此类推,归并完所有。

    时间复杂度分析是个小问题, merge 2 sorted list的复杂度是O(n),本以为结果就是O(n * k)。

    但是仔细考虑,随着归并不断进行,其中一个链表的长度不断增加,直至O(n * k),所以复杂度应该是O(n * k^2) 

    代码:

     1 /**
     2  * Definition for singly-linked list.
     3  * struct ListNode {
     4  *     int val;
     5  *     ListNode *next;
     6  *     ListNode(int x) : val(x), next(NULL) {}
     7  * };
     8  */
     9 class Solution {
    10 private:
    11      ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
    12         ListNode dummy(0);
    13         ListNode* head = &dummy;
    14         while (l1 != nullptr && l2 != nullptr) {
    15             if (l1 -> val < l2 -> val) {
    16                 head -> next = l1;
    17                 l1 = l1 -> next;
    18             }
    19             else {
    20                 head -> next = l2;
    21                 l2 = l2 -> next;
    22             }
    23             head = head -> next;
    24         }
    25         if (l1 != nullptr) {
    26             head -> next = l1;
    27         }
    28         if (l2 != nullptr) {
    29             head -> next = l2;
    30         }
    31         return dummy.next;
    32     }
    33 public:
    34     ListNode* mergeKLists(vector<ListNode*>& lists) {
    35         if (lists.size() == 0) {
    36             return nullptr;
    37         }
    38         ListNode dummy(0);
    39         ListNode* head = &dummy;
    40         head -> next = lists[0];
    41         for (int i = 1; i < lists.size(); ++i) {
    42             head -> next = mergeTwoLists(head->next, lists[i]);
    43         }
    44         return dummy.next;
    45         
    46     }
    47 };

    方法2:

    利用最小堆。将所有链表的第一个节点加入堆,然后每次取出值最小的节点,并将该节点的next节点加入堆中。堆为空后所以节点处理完,归并后链表。

    堆的大小为k,所以插入删除取节点复杂度均为O(logk),共对O(nk)个节点进行操作,所以时间复杂度为O(nklogk)。

    注:

    本题除了算法思想本身,还有对于实现过程还是有需要总结的。

    1) STL的priority_queue默认的是最大堆,需要重载比较函数。 

      首先一般来讲priority有三个参数,即

    template < class T, class Container = vector<T>,
               class Compare = less<typename Container::value_type> > class priority_queue;

    可以看出,2、3有缺省值,即表示用vector实现priority_queue,实现的是最大堆。所以可以不写这两个参数。

    但是如果要修改比较方式,即第三个参数的话,第二个参数也要给出(以前没用过,真是查文档才知道)。

    对于内置类型,如int,可以使用stl的functor如 greater<int>直接修改堆的大小属性,但是自定义节点,如本例的ListNode,需要自己重载。

    2)对于传入比较函数,一种方法是重载类的operator <,但是leetcode中ListNode的定义是不能修改的。

      还有就是写一个cmp函数,值得注意的是。funtor作为一个类需要重载其operator(),即对于本题,写为

        struct cmp{
          bool operator() (ListNode* l1, ListNode* l2) {  
              return l1 -> val > l2 -> val;
          }  
        };  

    另外,priority_queue的第三个参数不能只传函数,必须封装成个functor(类),开始写的时候传函数报错了。

    总之这题收货还是不少,不论从算法角度还是语言角度。

    代码:

     1 /**
     2  * Definition for singly-linked list.
     3  * struct ListNode {
     4  *     int val;
     5  *     ListNode *next;
     6  *     ListNode(int x) : val(x), next(NULL) {}
     7  * };
     8  */
     9 class Solution {
    10 private:
    11     struct cmp{
    12       bool operator() (ListNode* l1, ListNode* l2) {  //why?!
    13           return l1 -> val > l2 -> val;
    14       }  
    15     };  
    16 public:
    17     ListNode* mergeKLists(vector<ListNode*>& lists) {
    18         ListNode dummy(0);
    19         ListNode* head = &dummy;
    20         priority_queue<ListNode*, vector<ListNode*>, cmp> que;
    21         for (int i = 0; i < lists.size(); ++i) {
    22             if (lists[i] != nullptr) {
    23                 que.push(lists[i]);
    24             }
    25         }
    26         while (!que.empty()) {
    27             ListNode* temp = que.top();
    28             head -> next = temp;
    29             head = head -> next;
    30             que.pop();
    31             if (temp -> next != nullptr) {
    32                 que.push(temp->next);
    33             }
    34         }
    35         return dummy.next;
    36     }    
    37 };
  • 相关阅读:
    [USACO07JAN]平衡的阵容Balanced Lineup
    洛谷 P4389 付公主的背包 解题报告
    多项式Ⅱ
    半平面交 板子
    Problem C Dist 解题报告
    二维凸包的板子
    洛谷 P4841 城市规划 解题报告
    广二模拟赛 Problem A: 青春野狼不做理性小魔女的梦 解题报告
    CF 997E 解题报告
    洛谷 P4244 [SHOI2008]仙人掌图 II 解题报告
  • 原文地址:https://www.cnblogs.com/wangxiaobao/p/5768952.html
Copyright © 2011-2022 走看看