LeetCode: Sort List 解题报告

Sort List

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

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

LeetCode: Sort List 解题报告

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)