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

思路I: 选择排序

每次都比较各个list的头指针所指的val,取最小的那个。时间复杂度O(n*k)

class Solution {
public:
ListNode *mergeKLists(vector &lists) {
if(lists.empty()) return NULL;
ListNode *head = new ListNode(INT_MIN); //创建头指针,不指向任何List元素;最后返回的是head->next
head->next = lists[];
ListNode *p1;
ListNode *p2;
ListNode *tmp;
for(int i = ; i< lists.size(); i++)
{
p1 = head;
p2 = lists[i];
while(p1->next && p2)
{
if(p1->next->val <= p2->val) p1 = p1->next;
else
{
tmp = p1->next;
p1->next = p2;
p1 = p1->next;
p2 = p2->next;
p1->next = tmp;
}
}
if(p2)
{
p1->next = p2;
}
}
return head->next;
}
};

Result:Time Limit Exceeded

思路II: 最小堆。

时间复杂度:堆排序其实也是一种选择排序。只不过直接选择排序中,为了从R[1...n]中选择最大记录,需比较n-1次,然后从R[1...n-2]中选择最大记录需比较n-2次。事实上这n-2次比较中有很多已经在前面的n-1次比较中已经做过,而树形选择排序恰好利用树形的特点保存了部分前面的比较结果,因此可以减少比较次数。时间复杂度为O(nlogk)

堆排序思想参考:http://jingyan.baidu.com/article/5225f26b057d5de6fa0908f3.html

class Solution {
public:
ListNode *mergeKLists(vector<ListNode *> &lists) {
// 使用堆排序,
// 1. 选出每个链表的头来插入小顶堆中,
// 2. 再把堆顶接入合并链表中,
// 3. 被选出的指针后移再加入小顶堆中,回到2
// 4. 最后所有链表都为空时,返回合并链表的头指针
if(lists.empty()) return nullptr;
vector<ListNode* > heap;
heap.push_back(); //padding
// 1. 选出每个链表的头来插入小顶堆中,
for(int i = ; i != lists.size(); i ++){
if(lists[i]) heap.push_back(lists[i]);
}
makeHeap(heap);
// 2. 再把堆顶接入合并链表中,
ListNode head(-); // 合并链表的表头
ListNode* p = &head;
while(heap.size()>){
auto minNode = heap[];
p->next = minNode; // 接入链表
p = p->next;
// 3. 被选出的指针后移再加入小顶堆中,回到2
auto next = minNode->next;
if(next) {
heap[] = next;
}else{
swap(heap[], heap[heap.size()-]);
heap.pop_back();
}
minHeap(heap, );//加入新元素到堆顶后,自上向下调整
}
// 4. 最后所有链表都为空时,返回合并链表的头指针
return head.next;
}
// 建立小顶堆
// 自底向上
void makeHeap(vector<ListNode*> &heap){
// 从最后一个元素的父节点开始建立小顶堆
for(int i = (heap.size()-)/; i > ; i --){
minHeap(heap, i);
}
}
// 小顶堆,以第i个元素为根建立小顶堆
//位置从1开始,取元素时记得-1
// 自顶向下
void minHeap(vector<ListNode*> &heap, int i){
int l = i*;
int r = l+;
int least(i);
// 算出最小元素的位置
if((l< heap.size()) && heap[l]->val<heap[i]->val ){
// 如果没有超过边界并且左孩子比父亲小,则换
least = l;
}
if(r<heap.size() && heap[r]->val<heap[least]->val){
// 如果没有超过边界并且右孩子最小,则换
least = r;
}
if(least != i){
swap(heap[i], heap[least]);
minHeap(heap, least);//换了之后,继续向下调整
}
}
};

最小堆在C++中可以用优先队列来实现

/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/ struct cmp {
bool operator () (ListNode *a, ListNode *b) {
return a->val > b->val;
}
}; class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
priority_queue<ListNode*,vector<ListNode*>,cmp> queue;
for (int i = ; i < lists.size(); i++) {
if (lists[i] != NULL) {
queue.push(lists[i]);
}
} ListNode *head = new ListNode(INT_MIN);
ListNode *prev = head, *temp;
while (!queue.empty()) {
temp = queue.top();
queue.pop();
prev->next = temp;
prev = prev->next; if (temp->next != NULL) {
queue.push(temp->next);
}
}
return head->next;
}
};

优先队列默认从大到小排序,即大顶堆,所以这里我们需要改成小顶堆:

1. 基本类型(例如int)都可以用greater<type>声明小顶堆优先队列:

priority_queue<int, vector<int>, greater<int>> q

2. 自定义的数据结构必须自定义比较函数(如以上代码中定义的cmp),或者自定义 > 操作:

bool operator > (ListNode* a, ListNode* b){
return a->val > b->val;
}

思路III:归并排序

初始状态:6,202,100,301,38,8,1
第一次归并后:{6,202},{100,301},{8,38},{1},比较次数:3;
第二次归并后:{6,100,202,301},{1,8,38},比较次数:4;
第三次归并后:{1,6,8,38,100,202,301},比较次数:4;
reference: http://baike.baidu.com/link?url=ayX3MQx_CrmcjOxkL7EKhXukLH9pJKJsD1XDMaP6eQwvFfc-BtnQBUTsElRafXbxqhCFOIlKC5VsL14LgjEjIK 
归并排序时间复杂度O(nlogn)
/**
* 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) {
if(lists.empty()) return NULL; mergeSort(lists, , lists.size()-);
return lists[];
}
void mergeSort(vector<ListNode*>& lists, int start, int end){
if(start==end) return;
int mid = (start + end) >> ;
mergeSort(lists, start, mid);
mergeSort(lists, mid+, end);
merge(lists,start, mid+);
} void merge(vector<ListNode*>& lists, int lst1, int lst2){
ListNode* root = NULL;
ListNode* current = NULL; while(lists[lst1] && lists[lst2]){
if(lists[lst1]->val <= lists[lst2]->val){
if(!root){
root = lists[lst1];
current = root;
}
else{
current->next = lists[lst1];
current = current->next;
}
lists[lst1] = lists[lst1]->next;
}
else{
if(!root){
root = lists[lst2];
current = root;
}
else{
current->next = lists[lst2];
current = current->next;
}
lists[lst2] = lists[lst2]->next;
}
} while(lists[lst1]){
if(!root){
root = lists[lst1];
current = root;
}
else{
current->next = lists[lst1];
current = current->next;
}
lists[lst1] = lists[lst1]->next;
}
while(lists[lst2]){
if(!root){
root = lists[lst2];
current = root;
}
else{
current->next = lists[lst2];
current = current->next;
}
lists[lst2] = lists[lst2]->next;
} lists[lst1] = root;
}
};

23.Merge k Sorted Lists (Array, Queue; Sort)的更多相关文章

  1. 刷题23. Merge k Sorted Lists

    一.题目说明 这个题目是23. Merge k Sorted Lists,归并k个有序列表生成一个列表.难度为Hard,实际上并不难,我一次提交就对了. 二.我的解答 就是k路归并,思路很简单,实现也 ...

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

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

  3. 21.Merge Two Sorted Lists 、23. Merge k Sorted Lists

    21.Merge Two Sorted Lists 初始化一个指针作为开头,然后返回这个指针的next class Solution { public: ListNode* mergeTwoLists ...

  4. 23. Merge k Sorted Lists - LeetCode

    Question 23. Merge k Sorted Lists Solution 题目大意:合并链表数组(每个链表中的元素是有序的),要求合并后的链表也是有序的 思路:遍历链表数组,每次取最小节点 ...

  5. 蜗牛慢慢爬 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 ...

  6. [LeetCode] 23. Merge k Sorted Lists ☆☆☆☆☆

    转载:https://leetcode.windliang.cc/leetCode-23-Merge-k-Sorted-Lists.html 描述 Merge k sorted linked list ...

  7. [LeetCode] 23. Merge k Sorted Lists ☆☆

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

  8. [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 ...

  9. [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 ...

随机推荐

  1. Alpha冲刺 (4/10)

    前言 队名:拖鞋旅游队 组长博客:https://www.cnblogs.com/Sulumer/p/9979357.html 作业博客:https://edu.cnblogs.com/campus/ ...

  2. nginx详细应用

    一.nginx的基本功能 基本Http服务,可以作为Http代理服务器和反向代理服务器,支持通过缓存加速访问,可以完成简单的负载均衡和容错,支持包过滤功能,支持SSL 高级Http服务,可以进行自定义 ...

  3. Gakki赛高-团队介绍

    队名:Gakki赛高 队员学号(标记组长): 张朝玮(组长)201521123106 张翔 201521123107 陈伟泽 201521123111 李嘉廉 201521123091 侯帅军 201 ...

  4. Sqlserver 按照时间段统计数据

    WITH t1 ( [hour], title ) , ' 0:00:00--- 1:00:00' UNION ALL , ' 1:00:00--- 2:00:00' UNION ALL , ' 2: ...

  5. C#统计给定的文本中字符出现的次数,使用循环和递归两种方法

    前几天看了一个.net程序员面试题目,题目是”统计给定的文本中字符出现的次数,使用循环和递归两种方法“. 下面是我对这个题目的解法: 1.使用循环: /// <summary> /// 使 ...

  6. 在create-react-app创建的项目下允许函数绑定运算符

    前话 React的函数绑定一致是个问题,主要有下面几种方式: 事件处理器动态绑定 export default class Com extends React.Component { render() ...

  7. free命令学习 输出理解

    命令 [root@localhost ~]# free -m total used free shared buffers cached Mem: 7869 7651 218 1 191 5081 - ...

  8. EXCEL中如何删除透视表的多余汇总

    EXCEL中如何删除透视表的多余汇总 1)如下图,选中字段列,单击鼠标右键,在弹出的菜单中选择[字段设置]选项. 2)弹出[字段设置]对话框. 3)选择“分类汇总和筛选”选项卡,然后勾选“无”选项,单 ...

  9. POJ2226Muddy Fields

    题目:http://poj.org/problem?id=2226 巧妙建图:以行或列上的联通块作为点,每个泥格子作为边,求最小点覆盖就可以了! 于是用匈牙利算法找最大匹配.注意要对右部点记录每一个左 ...

  10. 现在就开始使用AngularJS的三个重要原因

    现在就开始使用AngularJS的三个重要原因 在线演示1 本地下载 如果你不熟悉什么是Angular.js的话,小编我强烈推荐你阅读 Javascript教程:AngularJS的五个超酷特性.简单 ...