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的这种情况。

 /**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode sortList(ListNode head) {
// Nodes should be more than 2.
if (head == null || head.next == null) {
return head;
} // get the mid node.
ListNode midPre = getMidPre(head); // Cut the two list.
ListNode right = midPre.next;
midPre.next = null; // Sort the left side and the right side.
ListNode left = sortList(head);
right = sortList(right); // Merge the two sides together.
return merge(left, right);
} // get the pre node before mid.
public ListNode getMidPre1(ListNode head) {
ListNode slow = head;
ListNode fast = head; while (fast != null && fast.next != null && fast.next.next != null) {
slow = slow.next;
fast = fast.next.next;
} return slow;
} // get the pre node before mid.
public ListNode getMidPre(ListNode head) {
ListNode slow = head; // fast提前一点儿。这样就可以得到前一个节点喽。
ListNode fast = head.next; while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
} return slow;
} public ListNode merge(ListNode head1, ListNode head2) {
ListNode dummy = new ListNode(0);
ListNode cur = dummy; while (head1 != null && head2 != null) {
if (head1.val < head2.val) {
cur.next = head1;
head1 = head1.next;
} else {
cur.next = head2;
head2 = head2.next;
} cur = cur.next;
} if (head1 != null) {
cur.next = head1;
} else {
cur.next = head2;
} return dummy.next;
}
}

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

 /*
The Solution 2:
Quick Sort.
*/
public ListNode sortList(ListNode head) {
if (head == null) {
return null;
} // Sort the list from 0 to len - 1
return quickSort(head);
} // The quick sort algorithm // All the elements are the same!
public boolean isDuplicate(ListNode head) {
while (head != null) {
if (head.next != null && head.next.val != head.val) {
return false;
} head = head.next;
} return true;
} public ListNode quickSort(ListNode head) {
if (head == null) {
return null;
} // 如果整个链是重复的,直接跳过。
if (isDuplicate(head)) {
return head;
} // Use the head node to be the pivot.
ListNode headNew = partition(head, head.val); // Find the pre position of the pivoit.
ListNode cur = headNew; ListNode dummy = new ListNode(0);
dummy.next = headNew; ListNode pre = dummy; // Find the pre node and the position of the piviot.
while (cur != null) {
if (cur.val == head.val) {
break;
} // move forward.
cur = cur.next;
pre = pre.next;
} // Cut the link to be three parts.
pre.next = null; // Get the left link;
ListNode left = dummy.next; // Get the right link.
ListNode right = cur.next;
cur.next = null; // Recurtion to call quick sort to sort left and right link.
left = quickSort(left);
right = quickSort(right); // Link the three part together. // Link the first part and the 2nd part.
if (left != null) {
dummy.next = left; // Find the tail of the left link.
while (left.next != null) {
left = left.next;
}
left.next = cur;
} else {
dummy.next = cur;
} cur.next = right; // The new head;
return dummy.next;
} // Return the new head;
public ListNode partition(ListNode head, int x) {
if (head == null) {
return null;
} ListNode dummy = new ListNode(0);
dummy.next = head; ListNode pre = dummy;
ListNode cur = head; // Record the big list.
ListNode bigDummy = new ListNode(0);
ListNode bigTail = bigDummy; while (cur != null) {
if (cur.val >= x) {
// Unlink the cur;
pre.next = cur.next; // Add the cur to the tail of the new link.
bigTail.next = cur;
cur.next = null; // Refresh the bigTail.
bigTail = cur; // 移除了一个元素的时候,pre不需要修改,因为cur已经移动到下一个位置了。
} else {
pre = pre.next;
} cur = pre.next;
} // Link the Big linklist to the smaller one.
pre.next = bigDummy.next; return dummy.next;
}

GITHUB:

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

LeetCode: Sort List 解题报告的更多相关文章

  1. LeetCode: Sort Colors 解题报告

    Sort ColorsGiven an array with n objects colored red, white or blue, sort them so that objects of th ...

  2. 【LeetCode】147. Insertion Sort List 解题报告(Python)

    [LeetCode]147. Insertion Sort List 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuemingzhu 个人博客: h ...

  3. LeetCode: Combination Sum 解题报告

    Combination Sum Combination Sum Total Accepted: 25850 Total Submissions: 96391 My Submissions Questi ...

  4. 【LeetCode】Permutations 解题报告

    全排列问题.经常使用的排列生成算法有序数法.字典序法.换位法(Johnson(Johnson-Trotter).轮转法以及Shift cursor cursor* (Gao & Wang)法. ...

  5. LeetCode - Course Schedule 解题报告

    以前从来没有写过解题报告,只是看到大肥羊河delta写过不少.最近想把写博客的节奏给带起来,所以就挑一个比较容易的题目练练手. 原题链接 https://leetcode.com/problems/c ...

  6. C#版 - LeetCode 148. Sort List 解题报告(归并排序小结)

    leetcode 148. Sort List 提交网址: https://leetcode.com/problems/sort-list/  Total Accepted: 68702 Total ...

  7. 【LeetCode】75. Sort Colors 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 计数排序 双指针 日期 题目地址:https://l ...

  8. 【LeetCode】148. Sort List 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...

  9. 【LeetCode】791. Custom Sort String 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 按顺序构造字符串 排序 日期 题目地址:https: ...

随机推荐

  1. How to hide the create button dynamical tree view in openerp ?

    <tree create="false" edit="false" > <tree attrs="{'create':[(" ...

  2. [Python]网络爬虫(六):一个简单的百度贴吧的小爬虫

    转自:http://blog.csdn.net/pleasecallmewhy/article/details/8927832 # -*- coding: utf-8 -*- #----------- ...

  3. Flash:DisplayObject的矩阵旋转(移动/修改注册点,修改旋转点)

    简单来说,原理就是利用matrix运算,先把旋转点移到原点位置,旋转变换后再恢复到原来的位置 var a:Sprite = new Sprite(); a.graphics.beginFill(0); ...

  4. const对象默觉得文件的局部变量

    const 定义的对象为一个常量不能被改动. 这个想必大家都知道. 这里仅仅是介绍const对象默觉得文件的局部变量         当一个非const变量在一个c或cpp文件里为全局时,它在整个程序 ...

  5. 使用Elasticsearch 与 NEST 库 构建 .NET 企业级搜索

    使用Elasticsearch 与 NEST 库 构建 .NET 企业级搜索 2015-03-26 dotNET跨平台 最近几年出现的云计算为组织和用户带来了福音.组织对客户的了解达到前所未有的透彻, ...

  6. TP3.2批量上传文件(图片),解决同名冲突问题

    1.html <form action="{:U('Upload/index')}" enctype="multipart/form-data" meth ...

  7. HDUOJ---Piggy-Bank

    Piggy-Bank Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total ...

  8. 解决LLDB模式下出现message sent to deallocated instance错误

    本文在源文的基础上做整理:http://www.devdiv.com/home.php?mod=space&uid=50901&do=blog&id=50856 Xcode版本 ...

  9. selenium 并发执行测试用例

    转帖: 要想多线程并发的运行WebDriver,必须同时满足2个条件,首先你的测试程序是多线程,其次需要用到Selenium Server(selenium-server-standalone-XXX ...

  10. libXext.so.6 libXp.so.6 libXt.so.6 is needed by openmotif21-2.1.30-11.el7.i686

    # rpm -ivh openmotif21--.el7.i686.rpm error: Failed dependencies: libXext.so. -.el7.i686 libXp.so. - ...