1. 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.

是的,这是一个非常简单链表操作问题。也许你只需要花几分种便能轻松写出代码。

2. Merge k Sorted Lists

我们现在来研究这个 问题

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

我们假设共有 \(k\) 条链表,且\(k\) 条链表的结点总数为 \(n\)

  1. 暴力:最直观的,我们脑海中会产生第一种做法,暴力暴力暴暴力

    • 我们每次从k个链表中取出其头节点,比较之后选出其中val值最小的结点,并将该结点指向其后继结点。非常显然,,我们需要比较\(nk\)次,这将导致时间复杂度趋近于\(O(nk)\)
    • 或许你可能会有另外一种想法,按照顺序,从第1,2个链表开始,两两合并,合并用到的正是上面第一个问题所用到的mergeTwoLists() 函数,然而每确定一个结点仍然需要比较\(k\)次,而总结点数为\(n\),时间复杂度仍然为\(O(nk)\),并没有任何改观,事实上你应该意识到,这两种思路其实是一样的,只不过一个是横向比较,一个是纵向比较。
  2. 最小堆 事实上,我们每次只需要从\(k\)个结点中得到val值最小的结点,而并非每次都需要比较这\(k\)个结点,这样看来,似乎我们能找到一个能够维护最值的数据结构,来降低时间复杂度。
    • 是的,你没有猜错,是它,就是它,我们的朋友,小哪吒。额,这个数据结构就叫做堆\((\text{heap})\)

      我们维护一个大小为\(k\)的小顶堆,每次pop出堆顶元素,并将其指向的链表后移,若后继结点不为空,将其push进堆,直到堆中不存在结点,算法结束。因为堆每一次modify操作只需要\(O(\log{k})\)的时间,所以时间复杂度降为\(O(n \log{k})\),awesome。
    • 想到,我们立马便会想到,还可以使用优先队列\((\text{priority_queue})\)来解决这个问题,两者的效果是一样的。
  3. 分治: 如前所述,暴力的方法有太多重复的比较,我们想到采用分治的办法来降低复杂度,是的,分而治之\((\text{Divide and Conquer})\),我们用归并排序的思想进行归并,同样可以将时间复杂度降到\(O(n \log{k})\)。另外,这里可以用迭代和递归两种形式来写。
  4. 还见到了一种方法,用vector将所有的结点指针存起来,按结点val值的大小进行排序,然后将排序后的指针一次连接起来,时间复杂度是\(O(n \log{n} )\),具体的就要看\(n\)与\(k\)的关系了,不过这也算是一种方法吧。
  5. 还有一种方法,用map将所有结点val值和其对应的个数映射起来,然后\(O(n)\)扫描,并逐个建立结点并连接起来,初一看,时间复杂度似乎是线性的,但是map的映射是需要耗时的,而结点的申请也是要耗时的,总的来说,挺巧妙的,时间复杂度应该也是在\(O(n \log{k})\)上下。

想了想,还是放几个代码好了。

class Solution {    //priority queue
public:
struct comp{
bool operator()( ListNode* a, ListNode* b ){
return a->val > b->val;
}
};
ListNode* mergeKLists(vector<ListNode*>& lists) {
priority_queue<ListNode*, vector<ListNode*>, comp > pq;
for( auto l: lists ){
if( l ) pq.push( l );
}
ListNode* dummy = new ListNode(-1);
ListNode* p = dummy;
while( !pq.empty() ){
ListNode* cur = pq.top();
pq.pop();
p->next = cur;
p = p->next;
cur = cur->next;
if( cur ) pq.push( cur );
}
return dummy->next;
}
}; class Solution { //heap
public:
static bool comp( ListNode* a, ListNode* b ){ return a->val > b->val; }
ListNode* mergeKLists(vector<ListNode*>& lists) {
vector<ListNode*> v;
for( auto l : lists ){
if( l ) v.push_back( l );
}
make_heap( v.begin(), v.end(), comp ); ListNode* dummy = new ListNode(-1), *p = dummy;
while( !v.empty() ){
ListNode* cur = v.front();
pop_heap( v.begin(), v.end(), comp );
v.pop_back();
p->next = cur; p = p->next; cur = cur->next;
if( cur ){
v.push_back( cur );
push_heap( v.begin(), v.end(), comp );
}
}
return dummy->next;
}
};

补充一下\(\text{STL}\)中\(\text{heap}\)的操作

\(\text{make_heap()}\):建堆,其中第三个参数是比较函数

\(\text{pop_heap()}\):pop_heap()不是真的把最大(最小)的元素从堆中弹出来。而是重新排序堆。它把first和last交换,然后将[first,last-1)的数据再做成一个堆

\(\text{push_heap()}\):push_heap()假设由[first,last-1)是一个有效的堆,再把堆中的新元素加进来,做成一个堆

\(\text{sort_heap()}\):sort_heap对[first,last)中的序列进行排序

Merge k Sorted Lists的更多相关文章

  1. 71. Merge k Sorted Lists

    Merge k Sorted Lists Merge k sorted linked lists and return it as one sorted list. Analyze and descr ...

  2. 【leetcode】Merge k Sorted Lists

    Merge k Sorted Lists Merge k sorted linked lists and return it as one sorted list. Analyze and descr ...

  3. 【LeetCode练习题】Merge k Sorted Lists

    Merge k Sorted Lists Merge k sorted linked lists and return it as one sorted list. Analyze and descr ...

  4. [Leetcode][Python]23: Merge k Sorted Lists

    # -*- coding: utf8 -*-'''__author__ = 'dabay.wang@gmail.com' 23: Merge k Sorted Listshttps://oj.leet ...

  5. LeetCode之“链表”:Merge Two Sorted Lists && Merge k Sorted Lists

    1. Merge Two Sorted Lists 题目链接 题目要求:  Merge two sorted linked lists and return it as a new list. The ...

  6. leetcode-algorithms-23 Merge k Sorted Lists

    leetcode-algorithms-23 Merge k Sorted Lists Merge k sorted linked lists and return it as one sorted ...

  7. python 中的堆 (heapq 模块)应用:Merge K Sorted Lists

    堆是计算机科学中一类特殊的数据结构的统称.堆通常是一个可以被看做一棵树的数组对象.在队列中,调度程序反复提取队列中第一个作业并运行,因为实际情况中某些时间较短的任务将等待很长时间才能结束,或者某些不短 ...

  8. 蜗牛慢慢爬 LeetCode 23. Merge k Sorted Lists [Difficulty: Hard]

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

  9. LeetCode: Merge k Sorted Lists 解题报告

    Merge k Sorted Lists Merge k sorted linked lists and return it as one sorted list. Analyze and descr ...

随机推荐

  1. 吉日嘎拉C#快速开发平台V4.0到V4.2升级记

    目前我用的版本是4.0的,也有近2年没更新了,狠了狠心升级一下,没想到真的行动起来,也没那么难! 用了3天时间,将吉日嘎拉的代码升级到了4.2版本,并让原来的DotNet.WebApplication ...

  2. [教学] Delphi Berlin 10.1 开发 Windows 10 平板 App 远程调试

    Delphi Berlin 10.1 开发 Windows 10 平板 App 远程调试安装步骤: 准备电脑: 一台开发电脑,安装 Delphi 开发环境 一台平板电脑,安装 PAServer,安装方 ...

  3. 基于SSH框架的学生公寓管理系统的质量属性

    系统名称:学生公寓管理系统 首先介绍一下学生公寓管理系统,在学生公寓管理方面,针对学生有关住宿信息问题进行管理,学生公寓管理系统主要包含了1)学生信息记录:包括学号.姓名.性别.院系.班级:2)住宿信 ...

  4. [ASP.NET Core] Static File Middleware

    前言 本篇文章介绍ASP.NET Core里,用来处理静态档案的Middleware,为自己留个纪录也希望能帮助到有需要的开发人员. ASP.NET Core官网 结构 一个Web站台最基本的功能,就 ...

  5. jqGrid几个需要注意的默认设置

    jqGrid中的option属性设置中,几乎每个属性都会给出默认值,然而,有些默认值实在有些坑爹,导致在使用过程中,如果没有注意到而使用了默认值,就会出现一些问题. height:是指jqGrid表格 ...

  6. jquery固定在顶部的导航菜单

    体验效果:http://hovertree.com/texiao/jquery/6.htm HTML文件代码: <!DOCTYPE html PUBLIC "-//W3C//DTD X ...

  7. 【HTML5&CSS3进阶学习01】气泡组件的实现

    前言 气泡组件在实际工作中非常普遍,无论是网页中还是app中,比如: 我们这里所谓气泡组件是指列表型气泡组件,这里就其dom实现,css实现,js实现做一个讨论,最后对一些细节点做一些说明,希望对各位 ...

  8. iOS 根据字符串数目,自定义Label等控件的高度

    利用分类,NSString,增加一个方法. #import <Foundation/Foundation.h> #import <UIKit/UIKit.h> @interfa ...

  9. iOS Xcode 打包之后,不能输出日志

    现象:一个项目,之前做的好好的,后来打包,生成ipa文件之后, 再运行的时候,NSLog的日志都不输出了. 解决方案: 在模式选择里面,里面包含:“Debug”.“Release”两种,设置“Debu ...

  10. Atitit.加密算法ati Aes的框架设计

    Atitit.加密算法ati Aes的框架设计 版本进化 c:\1t\aesC47.java c:\1t\aes.java 增加了public static byte[] encrypt(byte[] ...