Sort List

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

使用Merge Sort, 空间复杂度是 O(logN) 因为使用了栈空间。

SOLUTION 1:

使用Merge Sort来解决问题。

为什么不用QuickSort?
因为随机访问对于链表而言太耗时,而heap sort不可行。

注意,Find Mid用了2种解法。或者是让Fast提前结束,或是让Fast先走一步,目的就是要取得中间节点的前一个。这样做的目的,主要

是为了解决:

1->2->null

这一种情况。如果不这么做,slow会返回2.这样我们没办法切割2个Node的这种情况。

 1 /**
 2  * Definition for singly-linked list.
 3  * class ListNode {
 4  *     int val;
 5  *     ListNode next;
 6  *     ListNode(int x) {
 7  *         val = x;
 8  *         next = null;
 9  *     }
10  * }
11  */
12 public class Solution {
13     public ListNode sortList(ListNode head) {
14         // Nodes should be more than 2.
15         if (head == null || head.next == null) {
16             return head;
17         }
18
19         // get the mid node.
20         ListNode midPre = getMidPre(head);
21
22         // Cut the two list.
23         ListNode right = midPre.next;
24         midPre.next = null;
25
26         // Sort the left side and the right side.
27         ListNode left = sortList(head);
28         right = sortList(right);
29
30         // Merge the two sides together.
31         return merge(left, right);
32     }
33
34     // get the pre node before mid.
35     public ListNode getMidPre1(ListNode head) {
36         ListNode slow = head;
37         ListNode fast = head;
38
39         while (fast != null && fast.next != null && fast.next.next != null) {
40             slow = slow.next;
41             fast = fast.next.next;
42         }
43
44         return slow;
45     }
46
47     // get the pre node before mid.
48     public ListNode getMidPre(ListNode head) {
49         ListNode slow = head;
50
51         // fast提前一点儿。这样就可以得到前一个节点喽。
52         ListNode fast = head.next;
53
54         while (fast != null && fast.next != null) {
55             slow = slow.next;
56             fast = fast.next.next;
57         }
58
59         return slow;
60     }
61
62     public ListNode merge(ListNode head1, ListNode head2) {
63         ListNode dummy = new ListNode(0);
64         ListNode cur = dummy;
65
66         while (head1 != null && head2 != null) {
67             if (head1.val < head2.val) {
68                 cur.next = head1;
69                 head1 = head1.next;
70             } else {
71                 cur.next = head2;
72                 head2 = head2.next;
73             }
74
75             cur = cur.next;
76         }
77
78         if (head1 != null) {
79             cur.next = head1;
80         } else {
81             cur.next = head2;
82         }
83
84         return dummy.next;
85     }
86 }

View Code

SOLUTION 2:

使用快排也可以解决。但是注意,要加一个优化才可以过大数据,就是判断一下是不是整个链条是相同的节点,比如2 2 2 2 2 2 2 ,这样的就直接扫一次不用执行

快排,否则它会是N平方的复杂度。

参考资料:

https://oj.leetcode.com/discuss/3577/i-use-quick-sort-to-sort-the-list-but-why-i-get-time-limited

  1 /*
  2     The Solution 2:
  3     Quick Sort.
  4     */
  5     public ListNode sortList(ListNode head) {
  6         if (head == null) {
  7             return null;
  8         }
  9
 10         // Sort the list from 0 to len - 1
 11         return quickSort(head);
 12     }
 13
 14     // The quick sort algorithm
 15
 16     // All the elements are the same!
 17     public boolean isDuplicate(ListNode head) {
 18         while (head != null) {
 19             if (head.next != null && head.next.val != head.val) {
 20                 return false;
 21             }
 22
 23             head = head.next;
 24         }
 25
 26         return true;
 27     }
 28
 29     public ListNode quickSort(ListNode head) {
 30         if (head == null) {
 31             return null;
 32         }
 33
 34         // 如果整个链是重复的,直接跳过。
 35         if (isDuplicate(head)) {
 36             return head;
 37         }
 38
 39         // Use the head node to be the pivot.
 40         ListNode headNew = partition(head, head.val);
 41
 42         // Find the pre position of the pivoit.
 43         ListNode cur = headNew;
 44
 45         ListNode dummy = new ListNode(0);
 46         dummy.next = headNew;
 47
 48         ListNode pre = dummy;
 49
 50         // Find the pre node and the position of the piviot.
 51         while (cur != null) {
 52             if (cur.val == head.val) {
 53                 break;
 54             }
 55
 56             // move forward.
 57             cur = cur.next;
 58             pre = pre.next;
 59         }
 60
 61         // Cut the link to be three parts.
 62         pre.next = null;
 63
 64         // Get the left link;
 65         ListNode left = dummy.next;
 66
 67         // Get the right link.
 68         ListNode right = cur.next;
 69         cur.next = null;
 70
 71         // Recurtion to call quick sort to sort left and right link.
 72         left = quickSort(left);
 73         right = quickSort(right);
 74
 75         // Link the three part together.
 76
 77         // Link the first part and the 2nd part.
 78         if (left != null) {
 79             dummy.next = left;
 80
 81             // Find the tail of the left link.
 82             while (left.next != null) {
 83                 left = left.next;
 84             }
 85             left.next = cur;
 86         } else {
 87             dummy.next = cur;
 88         }
 89
 90         cur.next = right;
 91
 92         // The new head;
 93         return dummy.next;
 94     }
 95
 96     // Return the new head;
 97     public ListNode partition(ListNode head, int x) {
 98         if (head == null) {
 99             return null;
100         }
101
102         ListNode dummy = new ListNode(0);
103         dummy.next = head;
104
105         ListNode pre = dummy;
106         ListNode cur = head;
107
108         // Record the big list.
109         ListNode bigDummy = new ListNode(0);
110         ListNode bigTail = bigDummy;
111
112         while (cur != null) {
113             if (cur.val >= x) {
114                 // Unlink the cur;
115                 pre.next = cur.next;
116
117                 // Add the cur to the tail of the new link.
118                 bigTail.next = cur;
119                 cur.next = null;
120
121                 // Refresh the bigTail.
122                 bigTail = cur;
123
124                 // 移除了一个元素的时候,pre不需要修改,因为cur已经移动到下一个位置了。
125             } else {
126                 pre = pre.next;
127             }
128
129             cur = pre.next;
130         }
131
132         // Link the Big linklist to the smaller one.
133         pre.next = bigDummy.next;
134
135         return dummy.next;
136     }

View Code

GITHUB:

https://github.com/yuzhangcmu/LeetCode_algorithm/blob/master/list/SortList.java

LeetCode: Sort List 解题报告相关推荐

  1. [LeetCode] Multiply Strings 解题报告

    Given two numbers represented as strings, return multiplication of the numbers as a string. Note: Th ...

  2. Leetcode Weekly 188 解题报告

    文章目录 Leetcode 1441. 用栈操作构建数组 Leetcode 1442. 形成两个异或相等数组的三元组数目 Leetcode 1443. 收集树上所有苹果的最少时间 Leetcode 1 ...

  3. [LeetCode]Distinct Subsequences,解题报告

    题目 Given a string S and a string T, count the number of distinct subsequences of T in S. A subsequen ...

  4. LeetCode: Maximum Subarray 解题报告

    Maximum Subarray Find the contiguous subarray within an array (containing at least one number) which ...

  5. LeetCode: Add Binary 解题报告

    Add Binary Given two binary strings, return their sum (also a binary string). For example, a = " ...

  6. LeetCode 解题报告索引

    最近在准备找工作的算法题,刷刷LeetCode,以下是我的解题报告索引,每一题几乎都有详细的说明,供各位码农参考.根据我自己做的进度持续更新中......                        ...

  7. LeetCode第45场双周赛-解题报告

    LeetCode第45场双周赛-解题报告 A. 唯一元素的和 原题链接 https://leetcode-cn.com/problems/sum-of-unique-elements/ 解题思路 因为 ...

  8. LeetCode解题报告汇总

    LeetCode解题报告: [LeetCode]1.Two Sum - Yoona - 博客频道 - CSDN.NET [LeetCode]2.Add Two Numbers - Yoona - 博客 ...

  9. 【LeetCode】436. Find Right Interval 解题报告(Python)

    [LeetCode]436. Find Right Interval 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuemingzhu 个人博客: h ...

最新文章

  1. C++ 数字、string 简便互转
  2. SQL Server温故系列(1):SQL 数据操作 CRUD 之增删改合
  3. Swift 3.1新改动
  4. 40个漂亮的单页网站设计案例(上篇)
  5. CH9102 USB转串口应用体验
  6. log4j的8个日志级别(OFF、FATAL、ERROR、WARN、INFO、DEBUG、TRACE、 ALL)
  7. php排序算法算法,PHP排序算法之基数排序(Radix Sort)实例详解
  8. 现在没有可用的软件包 *** ,但是它被其它的软件包引用了 和 E: 无法定位软件包 ***问题解决(思路清晰干货)
  9. python打不开settings_python - django无法导入settings文件
  10. Qt初学者的一些学习方法、参考资料
  11. NVIDIA历史驱动下载
  12. 《代码整洁之道》读书笔记
  13. 改变CSS世界纵横规则的writing-mode属性
  14. 没有他的帅气,也要像他那般努力!(转载)
  15. 电脑端哔哩哔哩视频下载
  16. 96微信编辑器html在哪里,96微信编辑器怎么把文章生成链接?
  17. docker 出现错误:no such file or directory. Are you trying to connect to a TLS-enabled daemon without TLS
  18. 服务器cpu占用率高怎么解决,线上服务器CPU占用率高怎么办?
  19. UIColor延伸:判断两个颜色是否相等
  20. 发送邮件常见出错代码

热门文章

  1. PHP仿金蝶云ERP进销存V8网络多仓版源码
  2. Argon-Theme 一个非常好看的轻盈,简洁,美观的 WordPress 主题
  3. zblog音频MP3播放器插件
  4. 蓝色版去水印小程序源码+接口
  5. 疯传社群源码v7.8.0 测试可用 修复绿色版
  6. 简洁自适应个人码农主页源码
  7. 随行笔记小程序个人信息页源码
  8. C#联通新版验证码识别的实现[转]
  9. 8.8.8.8,Google推出免费DNS解析服务器
  10. 5.1.1越狱后必装插件!