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

思路:这题最容易想到的是,(假设有k个链表)链表1、2合并,然后其结果12和3合并,以此类推,最后是123--k-1和k合并。至于两链表合并的过程见merge two sorted lists的分析。复杂度的分析见JustDoIT的博客。算法复杂度:假设每个链表的平均长度是n,则1、2合并,遍历2n个节点;12结果和3合并,遍历3n个节点;....123...k-1的结果和k合并,遍历kn个节点,总共遍历n(2+3+4+....k)=n*(k^2+k-2)/2,因此时间复杂度是O(n*(k^2+k-2)/2)=O(nk^2)。     其次,可以想到用分治的思想,两两合并直至最后。

针对方法一,

 class Solution {
public:
//用向量存储链表
ListNode *mergeKLists(vector<ListNode *> &lists)
{
if(lists.size()==) return NULL;
ListNode *res=lists[]; //取出第一个链表
for(int i=;i<lists.size();i++) //反复调用
res=mergeTwoList(res,lists[i]); return res;
} //归并排序
ListNode *mergeTwoList(ListNode *head1,ListNode *head2)
{
ListNode node(); //创建头结点的前置结点
ListNode *res=&node;
while(head1&&head2)
{
if(head1->val<=head2->val)
{
res->next=head1;
head1=head1->next;
}
else
{
res->next=head2;
head2=head2->next;
}
res=res->next;
} if(head1)
res->next=head1;
else if(head2)
res->next=head2; return node.next;
}
};

针对方法二:比较难想的是,两两合并时,链表的选取。

 /**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *mergeKLists(vector<ListNode *> &lists)
{
int len=lists.size();
if(len==)
return NULL; while(len>)
{
int k=(len+)>>; for(int i=;i<len/;++i)
{
lists[i]=mergeTwoLists(lists[i],lists[i+k]);
}
len=k;
}
return lists[];
} ListNode *mergeTwoLists(ListNode *head1,ListNode *head2)
{
ListNode *nList=new ListNode(-);
nList->next=head1;
ListNode *pre=nList; while(head1&&head2)
{
if(head1->val >head2->val)
{
pre->next=head2;
head2=head2->next;
}
else
{
pre->next=head1;
head1=head1->next;
}
pre=pre->next;
} if(head1)
{
pre->next=head1;
}
else
pre->next=head2; return nList->next;
}
};

还有一种方法是最小堆的方法,维护一个大小为k的最小堆,初始化堆中的元素为每个链表的表头,它们会自动排好序,然后取出其中的最小元素介入新的链表中,然后,将最小元素的后继压入堆中,下次再从堆中选取最小的元素。元素加入堆中的复杂度为O(longk),总共有kn个元素加入堆中,因此,复杂度也和算法2一样是O(nklogk)。具体代码如下:

 class Solution
{
private:
struct cmp
{
bool operator()(const ListNode *a,const ListNode *b)
{
return a->val >b->val;
}
}
public:
//用向量存储链表
ListNode *mergeKLists(vector<ListNode *> &lists)
{
int n=lists.size();
if (n==) return NULL; ListNode node();
ListNode *res=&node; priority_queue<ListNode*,vector<ListNode*>,cmp> que; for(int i=;i<n;i++)
{
if(lists[i])
que.push(list[i]);
} while(! que.empty())
{
ListNode *p=que.top();
que.pop();
res->next=p;
res=p; if(p->next)
que.push(p->next);
} return node.next;
}
}

此篇中,有很多分析过程都是来自JustDoITGrandyang的博客。

[Leetcode] Merge k sorted lists 合并k个已排序的链表的更多相关文章

  1. [LeetCode] Merge k Sorted Lists 合并k个有序链表

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

  2. [LeetCode] 23. Merge k Sorted Lists 合并k个有序链表

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

  3. 【LeetCode】23. Merge k Sorted Lists 合并K个升序链表

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 个人公众号:负雪明烛 本文关键词:合并,链表,单链表,题解,leetcode, 力扣,Py ...

  4. Leetcode23--->Merge K sorted Lists(合并k个排序的单链表)

    题目: 合并k个排序将k个已排序的链表合并为一个排好序的链表,并分析其时间复杂度 . 解题思路: 类似于归并排序的思想,lists中存放的是多个单链表,将lists的头和尾两个链表合并,放在头,头向后 ...

  5. 【LeetCode每天一题】 Merge k Sorted Lists(合并K个有序链表)

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

  6. [LeetCode]23. Merge k Sorted Lists合并K个排序链表

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

  7. 023 Merge k Sorted Lists 合并K个有序链表

    合并K个有序链表,并且作为一个有序链表的形式返回.分析并描述它的复杂度. 详见:https://leetcode.com/problems/merge-k-sorted-lists/descripti ...

  8. [Leetcode] Merge two sorted lists 合并两已排序的链表

    Merge two sorted linked lists and return it as a new list. The new list should be made by splicing t ...

  9. [LeetCode] 21. Merge Two Sorted Lists 合并有序链表

    Merge two sorted linked lists and return it as a new list. The new list should be made by splicing t ...

随机推荐

  1. mac 安装requests

    首先mac上已经安装了python,我的是python2x,我自己安装了python3,python3安装requests,控制台,输入,pip3 install requests 下面就已经安装完成 ...

  2. hadoop生态搭建(3节点)-01.基础配置

    # 基础配置# ==================================================================node1 vi /etc/hostname nod ...

  3. java第二章 变量和运算符

      Java 基础应用编程——  变量和运算符 1.Java程序结构          数据类型:确定要存储在内存中的数据的类型.          变量:是存储数据的基本单元 2.变量的概念   变 ...

  4. windows下subversion服务器搭建

    一.下载subversion服务器端和客户端软件 1.subversion下载地址:http://subversion.tigris.org/ 2.svn比较流行的客户端Tortoisesvn下载地址 ...

  5. Bootstrap4用法

    #Bootstrap4 ## 网格系统- .col- 针对所有设备- .col-sm- 平板 - 屏幕宽度等于或大于 576px- .col-md- 桌面显示器 - 屏幕宽度等于或大于 768px)- ...

  6. Linux 文件与目录管理命令

    处理目录的常用命令 常见的处理目录的命令: ls: 列出目录 cd:切换目录 pwd:显示目前的目录 mkdir:创建一个新的目录,语法:mkdir [-mp] 目录名称 -m :配置文件的权限 -p ...

  7. 第十一篇 Python函数之定义&形参&实参&位置参数&关键字参数&可变长参数&默认参数

    函数的定义:函数是为了完成某一特定功能的,函数是逻辑结构化和过程化的一种编程方法 函数的定义格式,函数一般都是有返回值的 #语法 #函数名要能反映其意义 def 函数名(参数1,参数2,参数3,... ...

  8. java 读取配置文件 与更新

    笔记 public class Config { private static Properties props = new Properties(); static File configFile ...

  9. C++ STL容器——stack用法介绍

    stack是一种容器适配器,专门设计用于在LIFO上下文中操作(后进先出),其中元素仅从容器的一端插入和删除. 容器适配器,而不是一种容器. 它是容器适配器是指,只要支持一系列方法的容器(empty, ...

  10. ubuntu安装显卡驱动和cuda

    NVIDIA-linux.run安装后,会出现登录页面循环,解决办法是在运行命令后加入-no-opengl-files 打开nvidia x server Settings软件,显示:You do n ...