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 };
时间: 2024-12-03 04:46:02

LeetCode23 Merge k Sorted Lists的相关文章

LeetCode23 Merge k Sorted Lists 把K个有序链表连接成一个

题目: Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. 翻译: 把K个有序的链表合成一个,返回. 思路: 这道题和昨天的Merge 2 Lists有些类似.但是k不确定,如果用每个都去遍历的话,肯定是不会通过的. So.可以想到的是归并方法. 还记得大一刚开始组长布置的归并作业,那时候刚入门,看的云里雾里. 正好借此机会把归并好好的复习一下. 先说

【leetcode】Merge k Sorted Lists

Merge k Sorted Lists Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. 采用优先队列priority_queue 把ListNode放入优先队列中,弹出最小指后,如果该ListNode有下一个元素,则把下一个元素放入到队列中 1 /** 2 * Definition for singly-linked list. 3 * stru

Merge k Sorted Lists

Merge k Sorted Lists Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. 根据k个已经排好序的链表构造一个排序的链表,采用类似归并排序的算法可以通过测试 /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next;

[LeetCode]23. Merge k Sorted Lists

23. Merge k Sorted Lists Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. 给定k个排序了的链表,合并k个链表成一个排序链表. 本程序思路: 1)首先得到K个链表的长度和存在len中 2)从K个链表中找到值最小的那个节点,把该节点添加到合并链表中 3)重复len次即可把所有节点添加到合并链表中. 注意事项: 1)K个链表中有的

Leetcode 23.Merge Two Sorted Lists Merge K Sorted Lists

Merge Two Sorted Lists Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists. 依次拼接 复杂度 时间 O(N) 空间 O(1) 思路 该题就是简单的把两个链表的节点拼接起来,我们可以用一个Dummy头,将比较过后的节点接在这个Dummy头之后.最后

leetcode 刷题之路 93 Merge k Sorted Lists

Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. 将k个有序链表合并成一个有序链表. 思路,之前做过两个有序链表的合并操作,对于k个链表,我们最先想到的就是能不能转化为我们熟悉的两个链表的合并,可以我们先将k个链表分为两部分,先对这两部分完成链表的有序合并操作,再对合并得到的两个链表进行合并,这是一个递归性质的描述,采用递归很容易实现这个程序,和数组

[leetcode]Merge k Sorted Lists @ Python

原题地址:https://oj.leetcode.com/problems/merge-k-sorted-lists/ 题意:Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. 解题思路:归并k个已经排好序的链表.使用堆这一数据结构,首先将每条链表的头节点进入堆中,然后将最小的弹出,并将最小的节点这条链表的下一个节点入堆,依次类推,最终形成的链表就是归

LeetCode: Merge k Sorted Lists [022]

[题目] Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. [题意] 合并K个有序链表 [思路] 归并 [代码] /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), n

leetCode 23. Merge k Sorted Lists (合并k个排序链表) 解题思路和方法

Merge k Sorted Lists Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. 思路:此题是由合并两个排序链表演化而来,刚开始,想法比较简单,像求最大公共前缀一样,逐一求解:但是最后超时,所以马上意识到出题方是为了使用归并和分治的方法,故重新写了代码. 代码一(超时未过): /** * Definition for singly-link