合并k个已经排好序的数列是面试中也比较容易被问到的一个算法,有很多种解决,其中第一时间比较容易想到的解法如下:

对于这三组从小到大的数列:

如此循环,最终就将三个已经排序的数列的数字按从小到大的顺序排序到最终结果集了,那先来看一下这种算法的时间复杂度:

如果总共有k个排序好的数列,而几个数列中的总数字为n个,每拿一个数都要进行k次的循环比较,很明显其时间复杂度T(n) = O(n*k)

那如果面试官问你如何对它进行优化呢?也就是用一个效率更高的算法来代替它,这时就需要用到之前学过的最小堆去优化啦,因为每次最小堆的根结点就是该数列的最小值,所以说用最小堆去实现的话也就是将每个数列中待比较的数字都放到最小堆中,其中涉及到交换元素,最终拿根结点就可以拿到最小的值了,这样对于k个数列来说其时间复杂度也就是logk,比之前的要比较k次才能得到最小值效率要高,也就是利用最小堆实现合并排序数列的时间复杂度T(n) = O(n * logk),当k值越大时,其logk比k远远要小很多,当然如果K值比较小其优化力度体现不是特别明显,所以在回答面试官时需要强调:在K值比较多的情况下用最小堆去优化是一个比较好的方案。

所以接下来就是来看一下如何来实现这种优化的算法,这里采用JAVA来实现,因为实现起来也比较好理由,下面先来搭建框架:

import java.util.ArrayList;
import java.util.Comparator;
import java.util.PriorityQueue; public class MergeKList { //用链表来表达数列
static class ListNode {
int value;
ListNode next; ListNode(int value) {
this.value = value;
}
} //开始合并有序序列
private void mergeKLists(ArrayList<ListNode> lists) {
//TODO
} public static void main(String[] args) {
//构造三个有序数列
ListNode h1 = new ListNode(2);
h1.next = new ListNode(5);
h1.next.next = new ListNode(7); ListNode h2 = new ListNode(3);
h2.next = new ListNode(9);
h2.next.next = new ListNode(10); ListNode h3 = new ListNode(1);
h3.next = new ListNode(4); ArrayList<ListNode> lists = new ArrayList<ListNode>();
lists.add(h1);
lists.add(h2);
lists.add(h3); new MergeKList().mergeKLists(lists);
} }

接着就是实现核心的合并方法:mergeKLists(),这里需要涉及到优先队列:PriorityQueue:

其中它就是用堆来实现的,所以功能跟堆类似,将一堆数字添加到优先队列中,最终拿的话按一定的条件拿。对于Queue我们已经非常熟了,先进先出,也就是先进去的先出来,但是!!这个优先队列是按条件来出的,可以最小的元素先出来,有了这么一个现成的类那实现就显得异常简单啦,所以这也是为啥要采用java来实现的原因,具体如下:

import java.util.ArrayList;
import java.util.Comparator;
import java.util.PriorityQueue; public class MergeKList { //用链表来表达数列
static class ListNode {
int value;
ListNode next; ListNode(int value) {
this.value = value;
}
} //开始合并有序序列
private void mergeKLists(ArrayList<ListNode> lists) {
PriorityQueue<ListNode> q = new PriorityQueue<ListNode>(lists.size(),
new Comparator<ListNode>(){
public int compare(ListNode a, ListNode b) {
return a.value - b.value;
}
}); //将每个序列的数添加到优先队列中
for(ListNode list : lists) {
q.add(list);
} while(q.size() > 0) {
ListNode temp = q.poll();//直接拿出最小的元素,由优先队列类来保证
System.out.println(temp.value);
if(temp.next != null)
q.add(temp.next);//如果当前序列有下一个元素则直接将它再加入到优先队列中
}
} public static void main(String[] args) {
//构造三个有序数列
ListNode h1 = new ListNode(2);
h1.next = new ListNode(5);
h1.next.next = new ListNode(7); ListNode h2 = new ListNode(3);
h2.next = new ListNode(9);
h2.next.next = new ListNode(10); ListNode h3 = new ListNode(1);
h3.next = new ListNode(4); ArrayList<ListNode> lists = new ArrayList<ListNode>();
lists.add(h1);
lists.add(h2);
lists.add(h3); new MergeKList().mergeKLists(lists);
} }

编译运行:

由于比较简单,所以这里就不debug啦~~

合并K个sorted list的更多相关文章

  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. [Swift]LeetCode23. 合并K个排序链表 | Merge k Sorted Lists

    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个有序链表)

    题目链接: https://leetcode.com/problems/merge-k-sorted-lists/?tab=Description Problem: 给出k个有序的list, 将其进行 ...

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

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

  6. LeetCode 23. 合并K个排序链表(Merge Two Sorted Lists)

    23. 合并K个排序链表 23. Merge k Sorted Lists 题目描述 合并 k 个排序链表,返回合并后的排序链表.请分析和描述算法的复杂度. LeetCode23. Merge k S ...

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

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

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

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

  9. LeetCode 23. 合并K个排序链表(Merge k Sorted Lists)

    题目描述 合并 k 个排序链表,返回合并后的排序链表.请分析和描述算法的复杂度. 示例: 输入: [   1->4->5,   1->3->4,   2->6 ] 输出: ...

随机推荐

  1. Linux系统封装成iso文件

    #安装所需软件包yum -y install createrepo mkisofs anaconda-runtime 根据root下的install.log文件,得到安装的软件包awk '/Insta ...

  2. day16 模块导入及环境变量

    """ 今日内容: 1.模块 2.模块的导入 3.环境变量sys.path 4.模块间的相互调用 """ """ ...

  3. 自学电脑游戏第四天(Swing)

    继续之前的 3.组合框(JComboBox) 例题:利用JComboBox设计一个选择城市的程序. import java.awt.*; import javax.swing.*; public cl ...

  4. sql sever 授予用户create table权限

    sql server2008的用户权限管理及其细致.此处我也不知道是表扬还是批评.所以经常会遇到各种“对不起您没有**权限”的问题. 本次遇到的问题机器常见.在尝试修改数据库结构时提示"没有 ...

  5. Synchronized与Lock的区别与应用场景

    转载. https://blog.csdn.net/fly910905/article/details/79765381 同步代码块,同步方法,或者是用java提供的锁机制,我们可以实现对共享资源变量 ...

  6. [SDOI2013]直径 题解

    题面 这道题明显的一定要找到直径的具体路径,所以两遍dfs是比较好的选择: 第一问是一道弱智题吧? 主要难度全部分摊在了第二问: 其实不难,先找到任意一个直径: 对于任意一个在直径上的点: 设nxt[ ...

  7. 石子合并(直线版+环形版)&(朴素写法+四边形优化+GarsiaWachs算法)

    石子合并-直线版 (点击此处查看题目) 朴素写法 最简单常见的写法就是通过枚举分割点,求出每个区间合并的最小花费,从而得到整个区间的最小花费,时间复杂度为O(n^3),核心代码如下: ; i < ...

  8. python新手必躺的5大坑

    python新手必躺的5大坑 对于Python新手来说,写代码很少考虑代码的效率和简洁性,因此容易造成代码冗长.执行慢,这些都是需要改进的地方.本文是想通过几个案列给新手一点启发,怎样写python代 ...

  9. springboot自动配置国际化失效分析

    最近在整理springBoot国际化时,发现国际化没有生效,通过报错提示在 MessageTag -> doEndTag处打断点 最后发现messageSource并不是ResourceBund ...

  10. thymeleaf 模板使用 之 解决因HTML标签未闭合引起的错误

    一.修改thymeleaf属性配置 spring.thymeleaf.prefix=classpath:/templates/ spring.thymeleaf.suffix=.html spring ...