LeetCode-Sort List 链表排序
原题链接: http://oj.leetcode.com/problems/sort-list/
对链表进行排序,要求的时间复杂度为O(n log n)。nlogn的排序有快速排序、归并排序、堆排序。双向链表用快排比较适合,堆排序也可以用于链表,单向链表适合用归并排序。题目要求的是常数的空间复杂度,因为这里用了递归,如果算上栈空间的话,也要 o(logn)的复杂度。
关于链表的划分,这里使用了快慢指针,从中间节点进行切开成单独的链表。在merge之后又会合并成一个链表。
以下分别用归并排序和快速排序实现(Java),遗憾的是快速排序的实现超时了,毕竟交换数据的次数过多,没有归并排序之家更换指针要快。快速排序的实现大家可以忽略,代码写的不太好。
关于链表的归并排序可参考之前的一篇文章归并排序对链表进行排序
,只是实现比下面这个有些复杂。
1. 归并排序实现
01
|
public class MergetSortList {
|
02
|
03
|
public static ListNode sortList(ListNode head) {
|
04
|
if (head == null || head.next == null ) return head;
|
05
|
ListNode slow = head;
|
06
|
ListNode fast = head;
|
07
|
//用快慢指针找到中间节点
|
08
|
while (fast.next != null && fast.next.next != null ){
|
09
|
slow = slow.next;
|
10
|
fast = fast.next.next;
|
11
|
}
|
12
|
ListNode list2 = slow.next;
|
13
|
slow.next = null ;
|
14
|
head = sortList(head);
|
15
|
list2 = sortList(list2);
|
16
|
return merge(head, list2);
|
17
|
}
|
18
|
19
|
private static ListNode merge(ListNode list1, ListNode list2) {
|
20
|
if (list1 == null ) return list2;
|
21
|
if (list2 == null ) return list1;
|
22
|
ListNode newHead = new ListNode( 0 ); //链表头不存储实际数据
|
23
|
ListNode last = newHead;
|
24
|
last = newHead;
|
25
|
//连接每个节点,只更换指针,因此空间复杂度为O(1)
|
26
|
while (list1 != null && list2 != null ){
|
27
|
if (list1.val < list2.val){
|
28
|
last.next = list1;
|
29
|
list1 = list1.next;
|
30
|
} else {
|
31
|
last.next = list2;
|
32
|
list2 = list2.next;
|
33
|
}
|
34
|
last = last.next;
|
35
|
}
|
36
|
//最后剩余的部分,直接连接起来即可
|
37
|
if (list1 != null ) last.next = list1;
|
38
|
else if (list2 != null ) last.next = list2;
|
39
|
return newHead.next;
|
40
|
}
|
41
|
42
|
public static void main(String[] args) {
|
43
|
ListNode l1 = new ListNode( 8 );
|
44
|
ListNode l2 = new ListNode( 7 );
|
45
|
ListNode l3 = new ListNode( 6 );
|
46
|
ListNode l4 = new ListNode( 5 );
|
47
|
ListNode l5 = new ListNode( 4 );
|
48
|
ListNode l6 = new ListNode( 3 );
|
49
|
50
|
l1.next = l2;
|
51
|
l2.next = l3;
|
52
|
l3.next = l4;
|
53
|
l4.next = l5;
|
54
|
l5.next = l6;
|
55
|
56
|
l1 = sortList(l1);
|
57
|
58
|
while (l1 != null ){
|
59
|
System.out.print(l1.val + " " );
|
60
|
l1 = l1.next;
|
61
|
}
|
62
|
}
|
63
|
}
|
2.快速排序实现
01
|
//以end节点作为pivot进行划分,返回划分的节点的前一个节点
|
02
|
public static ListNode partition(ListNode head, ListNode end){
|
03
|
int pivot = end.val;
|
04
|
ListNode lastSmallNode = null ;
|
05
|
ListNode tmpHead = head;
|
06
|
while (tmpHead != end){
|
07
|
if (tmpHead.val < pivot){
|
08
|
if (lastSmallNode == null ) lastSmallNode = head;
|
09
|
else lastSmallNode = lastSmallNode.next;
|
10
|
int tmp = lastSmallNode.val;
|
11
|
lastSmallNode.val = tmpHead.val;
|
12
|
tmpHead.val = tmp;
|
13
|
}
|
14
|
tmpHead = tmpHead.next;
|
15
|
}
|
16
|
//有可能是划分的节点就是第一个,此时返回null
|
17
|
if (lastSmallNode == null ){
|
18
|
end.val = head.val;
|
19
|
head.val = pivot;
|
20
|
return null ;
|
21
|
} else {
|
22
|
end.val = lastSmallNode.next.val;
|
23
|
lastSmallNode.next.val = pivot;
|
24
|
return lastSmallNode;
|
25
|
}
|
26
|
}
|
27
|
28
|
public static void quickSort(ListNode head, ListNode end){
|
29
|
if ( head == null || head == end || end == null || head.next == null ) return ;
|
30
|
ListNode mid = partition(head, end);
|
31
|
quickSort(head, mid);
|
32
|
//空表示,划分点是第一个位置
|
33
|
if (mid == null )
|
34
|
quickSort(head.next, end);
|
35
|
//如果划分点是最后一个位置,就无需再排序
|
36
|
else if (mid != end && mid.next != null && mid.next != end)
|
37
|
quickSort(mid.next.next, end);
|
38
|
}
|
39
|
40
|
public static ListNode sortList(ListNode head) {
|
41
|
if (head == null || head.next == null ) return head;
|
42
|
ListNode tail = head;
|
43
|
while (tail.next != null )
|
44
|
tail = tail.next;
|
45
|
quickSort(head,tail);
|
46
|
return head;
|
47
|
}
|
LeetCode-Sort List 链表排序相关推荐
- LeetCode 147. Insertion Sort List 链表插入排序 C++/Java
LeetCode 147. Insertion Sort List 链表插入排序 C++/Java Sort a linked list using insertion sort. A graphic ...
- 【Leetcode -61.旋转链表 -82.删除排序链表中的重复元素Ⅱ】
Leetcode Leetcode -61.旋转链表 Leetcode -82.删除排序链表中的重复元素Ⅱ Leetcode -61.旋转链表 题目:给你一个链表的头节点 head ,旋转链表,将链表 ...
- leetcode 148 --- 链表排序
1 题目 链表排序 2 解法 2.1 冒泡排序 /*** struct ListNode {* int val;* struct ListNode *next;* };*/class Solution ...
- 【阿里面试】链表排序总结
题目:对单链表进行排序,要求不改变每个节点内的值. 1.首先自然而然地会想到快速排序,毕竟是一个经典的排序算法.但是在排序过程中要求不能改变节点中的值,就必须通过改变节点中的指针来交换节点.而且快速排 ...
- LeetCode Sort List
Sort a linked list in O(n log n) time using constant space complexity. 思路分析:这题要求在O(n log n) 和常量空间对单链 ...
- 面试题精选:单链表排序也能玩出花来
今天国庆节,祝大家中秋节快乐,顺便给大家拜个早年[狗头].不过最近还在准备面试的同学们不要浪太狠,还是要好好学习的鸭. 单链表的排序在数据结构类的面试题中简直是集大成者,什么排序.链表.链表删除.添加 ...
- 冒泡链表排序java_链表排序(冒泡、选择、插入、快排、归并、希尔、堆排序)...
以下排序算法的正确性都可以在LeetCode的链表排序这一题检测.本文用到的链表结构如下(排序算法都是传入链表头指针作为参数,返回排序后的头指针) struct ListNode { int val; ...
- 链表排序(冒泡、选择、插入、快排、归并、希尔、堆排序)
这篇文章分析一下链表的各种排序方法. 以下排序算法的正确性都可以在LeetCode的链表排序这一题检测.本文用到的链表结构如下(排序算法都是传入链表头指针作为参数,返回排序后的头指针) struct ...
- 链表排序(C语言)选择排序
#include <stdio.h> #include <stdlib.h> #include <time.h> //用到了time函数#define arrayS ...
- 单链表的应用--对单链表排序
对单链表进行排序,利用前文写好的链表的框架,在链表类中补充Sort方法. 对单链表排序 一.问题分析 二.代码分析 1.链表类LinkList 2.链表方法Sort 三.测试代码 1.主函数 2. ...
最新文章
- 票房破五十亿!用Python分析李焕英为啥能逆袭《唐探3》
- 走进JavaScript响应式编程(Reactive Programming)
- 最强写作AI竟然学会象棋和作曲,语言模型跨界操作引热议,在线求战
- python多线程爬虫实例-Python爬虫开发【第1篇】【多线程爬虫及案例】
- 三运放差分放大电路分析_三运放差分放大电路
- 倾斜模型精细化处理_万能三维模型修复神奇——模方
- PHP钩子的简单介绍
- 如约而至!第二期 Flink 极客训练营上线啦
- rootkit学习总结2
- android测行走距离,如何在Android中行走时计算距离?
- Python —— 数据科学的手段 (第2版)配套代码
- 禁止移动端微信内置浏览器调节字体大小
- kindle_Kindle颂歌
- 【信奥赛一本通】 1413:确定进制(详细代码)
- 鸭梨笔记本上市!!!超越苹果和微软!!
- mysql gbk排序规则_Mysql 字符集及排序规则
- 图片与文字排版-flex
- poi2009 切题记
- Ubuntu系统配置win10双系统
- 1700802088 韩晓忠
热门文章
- 【错误记录】Android Studio 编译报错 ( This Gradle plugin requires a newer IDE able to request IDE model leve )
- 【Java 网络编程】UDP API 简介 ( DatagramSocket | DatagramPacket )
- c free 使用MSDN library定制
- windows 域用户账号验证登陆
- 自定义 checkbox 新玩法 ?
- 用Jquery控制文本框只能输入数字和字母及jquery自定义方法$.fn
- HTTPS_SSL配置的步骤以及原理说明
- sql server 链接到oracle库,读取对应信息
- 【python初识】列表与函数模块
- 如何把单精度二进制数转换成十进制数?