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 }
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 }
GITHUB:
https://github.com/yuzhangcmu/LeetCode_algorithm/blob/master/list/SortList.java
posted on 2014-11-29 20:55 Yu's Garden 阅读(3524) 评论(4) 编辑 收藏 举报