题目:Sort List

Sort a linked list in O(n log n) time using constant space complexity

看题目有两个要求:1)时间复杂度为O(nlogn);2)空间复杂度为常数,即不能增设额外的空间。
满足这样要求的排序算法,我们首先想到快排,合并排序和堆排序。我们来分析下几种排序算法对时间和空间复杂度的要求,堆排序实现上过于繁琐,我们不做考虑。快排的最坏的时间复杂度是O(n^2),平均复杂度为O(nlgn),如果按照题目的严格要求显然快排是不满足的,而且快排的实现引入了递归操作,递归调用的栈空间严格意义上说也是额外空间。另外值得注意的一点是:链表不像数组一样,可以随机访问元素,链表必须顺序访问,所以一般的递归操作很难实现,虽然也可以实现哈,见该文:递归实现链表排序。对于归并排序,我们知道需要O(n)的空间复杂度,即需要一个临时数组来存放排好序的元素,显然也合理,但那是针对的是数组,对于链表,归并排序的空间复杂度为in-place sort,即不需要额外空间就可以完成。另外,归并排序还有一个比较好的优势是其稳定性。所以,对于本题的解法,我们首选归并排序。

归并排序有多种方式,总的来说有三种,1)递归;2)非递归;3)自然合并;详见本文:归并排序的三种实现方法。对于链表,采用非递归的方式更为高效,用以下的一幅图来说明非递归的方式:

将两两子列表进行合并组合,达到排序的目的。本题的代码如下,参考上文实现的。

 ListNode *sortList(ListNode *head)
{
assert(NULL != head);
if (NULL == head)
return NULL; ListNode *p = head;
int len = ; //get the length of link
while (NULL != p) {
p = p->next;
len ++;
} ListNode *temp = new ListNode();
temp->next = head; int interval = ; //合并子列表的长度
for (; interval <= len; interval *= ) {
ListNode *pre = temp;
ListNode *first = temp->next; //两段子列表的起始位置
ListNode *second = temp->next; while (NULL != first || NULL != second) {
int i = ;
while (i < interval && NULL != second) {
second = second->next; //将second移到第二段子列表的起始处
i ++;
} int fvisit = , svisit = ; //访问子列表的的次数<interval,保证列表中的元素全部能被访问
while (fvisit < interval && svisit < interval && NULL != first && NULL != second) {
if (first->val < second->val) {
pre->next = first;
pre = first;
first = first->next;
fvisit ++;
}
else {
pre->next = second;
pre = second;
second = second->next;
svisit ++;
}
}
while (fvisit < interval && NULL != first) {
pre->next = first;
pre = first;
first = first->next;
fvisit ++;
}
while (svisit < interval && NULL != second) {
pre->next = second;
pre = second;
second = second->next;
svisit ++;
}
pre->next = second;
first = second;
}
}
ListNode *retResult = temp->next;
delete temp;
temp = NULL;
return retResult;
}

Leetcode:148_Sort List | O(nlogn)链表排序 | Medium的更多相关文章

  1. [LeetCode]147. Insertion Sort List链表排序

    插入排序的基本思想 把排好的放在一个新的变量中,每次拿出新的,排进去 这个新的变量要有超前节点,因为第一个节点可能会有变动 public ListNode insertionSortList(List ...

  2. LeetCode 上最难的链表算法题,没有之一!

    题目来源于 LeetCode 第 23 号问题:合并 K 个排序链表. 该题在 LeetCode 官网上有关于链表的问题中标注为最难的一道题目:难度为 Hard ,通过率在链表 Hard 级别目前最低 ...

  3. 148. Sort List (java 给单链表排序)

    题目:Sort a linked list in O(n log n) time using constant space complexity. 分析:给单链表排序,要求时间复杂度是O(nlogn) ...

  4. STL 中的链表排序

    一直以来学习排序算法, 都没有在链表排序上下太多功夫,因为用得不多.最近看STL源码,才发现,原来即使是链表,也能有时间复杂度为O(nlogn)的算法, 大大出乎我的意料之外,一般就能想到个插入排序. ...

  5. 算法基础~链表~排序链表的合并(k条)

    算法基础~链表~排序链表的合并(k条) 1,题意:已知k个已排序链表头结点指针,将这k个链表合并,合并后仍然为有序的,返回合并后的头结点. 2,方法之间时间复杂度的比较: 方法1(借助工具vector ...

  6. 备战秋招之十大排序——O(nlogn)级排序算法

    时间复杂度O(nlogn)级排序算法 五.希尔排序 首批将时间复杂度降到 O(n^2) 以下的算法之一.虽然原始的希尔排序最坏时间复杂度仍然是O(n^2),但经过优化的希尔排序可以达到 O(n^{1. ...

  7. C语言 链表的使用(链表的增删查改,链表逆转,链表排序)

    //链表的使用 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #include< ...

  8. c语言:链表排序, 链表反转

    下面将实现链表排序的排序和遍历显示功能: 所定义的链表结构如下: head -> p1 -> p2 ->p3 ->....->pn; head的本身不作为数据节点,hea ...

  9. 链表插入和删除,判断链表是否为空,求链表长度算法的,链表排序算法演示——C语言描述

    关于数据结构等的学习,以及学习算法的感想感悟,听了郝斌老师的数据结构课程,其中他也提到了学习数据结构的或者算法的一些个人见解,我觉的很好,对我的帮助也是很大,算法本就是令人头疼的问题,因为自己并没有学 ...

随机推荐

  1. oracle 连接字符串的问题

    未指定的错误,发生了一个 Oracle 错误,但无法从 Oracle 中检索错误信息.数据类型不被支持. 原因是你用的ADO   for   ORACLE的驱动是微软的Microsoft OLE DB ...

  2. oracle --hint总结

    得到一条sql语句执行计划的常用方法:1.explain plan 命令  2.DBMS_XPLAN包3.sqlplus中的AUTOTRACE开关4.10046事件5.10053事件6.AWR报告或者 ...

  3. 二十一、proxyDesign 代理模式

    原理: 时序图: 代码清单: Printable public interface Printable { void setPrinterName(String name); String getPr ...

  4. 简化Getter 与 Setter 的插件 Lombok

    参考文档:https://www.jianshu.com/p/365ea41b3573 第一步:添加依赖 <dependency> <groupId>org.projectlo ...

  5. Python select模块学习

    select 是常用的异步socket 处理方法 一般用法: # iwtd,owtd,ewtd 分别为需要异步处理的读socket队列, 写socket队列(一般不用), 和错误socket队列, 返 ...

  6. Codeforces Round #547 (Div. 3) F 贪心 + 离散化

    https://codeforces.com/contest/1141/problem/F2 题意 一个大小为n的数组a[],问最多有多少个不相交的区间和相等 题解 离散化用值来做,贪心选择较前的区间 ...

  7. Python开发——5.函数

    一.函数的定义 def test(x) "The Function definitions" x += return x def:定义函数的关键字 test:函数名 ():定义形参 ...

  8. 支持复制粘贴word图片的文本编辑器

    下载并打开基于PHP环境的工程: 运行: 尝试使用文档复制后粘贴进来:   通过粘贴后,文档以及图片被粘贴进来了,看看html代码: 由此可看出图片全部使用img标签统一. 看看文档图片被放置在哪了: ...

  9. handoop安装部署集群

    hdfs 1.0版本 一个namenode (secordary namenode 2.0冷备份) 和多个datanode构成分布式文件系统 mapreduce 一个 jobtracker 协调 ta ...

  10. linux服务器时间同步失败解决方法

    linux服务器时间同步失败解决方法 1.为什么会时间不同步: ①计算机的时间是根据电脑晶振以固定频率震荡而产生的,由于晶振的不同或者老化,会导致电脑时间积累误差的产 (什么是电脑晶振:http:// ...