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

posted on 2014-11-29 20:55  Yu's Garden  阅读(3504)  评论(4编辑  收藏  举报

导航