zoukankan      html  css  js  c++  java
  • LeetCode: Sort List 解题报告

    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

  • 相关阅读:
    java学习日记-------------------------------------贪吃蛇
    java学习日记----------------为窗口添加背景图
    java学习日记-----------------------------弹弹球
    java学习日记----------------------封装的日期类MyDate
    java 学习日记---------简易学生信息管理系统
    第九次作业
    第八次作业
    第七次作业
    第六次作业
    第五次作业
  • 原文地址:https://www.cnblogs.com/yuzhangcmu/p/4131885.html
Copyright © 2011-2022 走看看