*Sort List

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

  1 /**
  2  * 本代码由九章算法编辑提供。没有版权欢迎转发。
  3  * - 九章算法致力于帮助更多中国人找到好的工作,教师团队均来自硅谷和国内的一线大公司在职工程师。
  4  * - 现有的面试培训课程包括:九章算法班,系统设计班,BAT国内班
  5  * - 更多详情请见官方网站:http://www.jiuzhang.com/
  6  */
  7 
  8 // version 1: Merge Sort
  9 public class Solution {            
 10     private ListNode findMiddle(ListNode head) {
 11         ListNode slow = head, fast = head.next;
 12         while (fast != null && fast.next != null) {
 13             fast = fast.next.next;
 14             slow = slow.next;
 15         }
 16         return slow;
 17     }    
 18 
 19     private ListNode merge(ListNode head1, ListNode head2) {
 20         ListNode dummy = new ListNode(0);
 21         ListNode tail = dummy;
 22         while (head1 != null && head2 != null) {
 23             if (head1.val < head2.val) {
 24                 tail.next = head1;
 25                 head1 = head1.next;
 26             } else {
 27                 tail.next = head2;
 28                 head2 = head2.next;
 29             }
 30             tail = tail.next;
 31         }
 32         if (head1 != null) {
 33             tail.next = head1;
 34         } else {
 35             tail.next = head2;
 36         }
 37 
 38         return dummy.next;
 39     }
 40 
 41     public ListNode sortList(ListNode head) {
 42         if (head == null || head.next == null) {
 43             return head;
 44         }
 45 
 46         ListNode mid = findMiddle(head);
 47 
 48         ListNode right = sortList(mid.next);
 49         mid.next = null;
 50         ListNode left = sortList(head);
 51 
 52         return merge(left, right);
 53     }
 54 }
 55 
 56 // version 2: Quick Sort 1
 57 public class Solution {
 58     public ListNode sortList(ListNode head) {
 59         if (head == null || head.next == null) {
 60             return head;
 61         }
 62         
 63         ListNode mid = findMedian(head); // O(n)
 64         
 65         ListNode leftDummy = new ListNode(0), leftTail = leftDummy;
 66         ListNode rightDummy = new ListNode(0), rightTail = rightDummy;
 67         ListNode middleDummy = new ListNode(0), middleTail = middleDummy;
 68         while (head != null) {
 69             if (head.val < mid.val) {
 70                 leftTail.next = head;
 71                 leftTail = head;
 72             } else if (head.val > mid.val) {
 73                 rightTail.next = head;
 74                 rightTail = head;
 75             } else {
 76                 middleTail.next = head;
 77                 middleTail = head;
 78             }
 79             head = head.next;
 80         }
 81         
 82         leftTail.next = null;
 83         middleTail.next = null;
 84         rightTail.next = null;
 85         
 86         ListNode left = sortList(leftDummy.next);
 87         ListNode right = sortList(rightDummy.next);
 88         
 89         return concat(left, middleDummy.next, right);
 90     }
 91     
 92     private ListNode findMedian(ListNode head) {
 93         ListNode slow = head, fast = head.next;
 94         while (fast != null && fast.next != null) {
 95             slow = slow.next;
 96             fast = fast.next.next;
 97         }
 98         return slow;
 99     }
100     
101     private ListNode concat(ListNode left, ListNode middle, ListNode right) {
102         ListNode dummy = new ListNode(0), tail = dummy;
103         
104         tail.next = left; tail = getTail(tail);
105         tail.next = middle; tail = getTail(tail);
106         tail.next = right; tail = getTail(tail);
107         return dummy.next;
108     }
109     
110     private ListNode getTail(ListNode head) {
111         if (head == null) {
112            return null;
113         } 
114        
115         while (head.next != null) {
116             head = head.next;
117         }
118         return head;
119     }
120 }
121 
122 // version 3: Quick Sort 2
123 /**
124  * Definition for ListNode.
125  * public class ListNode {
126  *     int val;
127  *     ListNode next;
128  *     ListNode(int val) {
129  *         this.val = val;
130  *         this.next = null;
131  *     }
132  * }
133  */ 
134 class Pair {
135     public ListNode first, second; 
136     public Pair(ListNode first, ListNode second) {
137         this.first = first;
138         this.second = second;
139     }
140 }
141 
142 public class Solution {
143     /**
144      * @param head: The head of linked list.
145      * @return: You should return the head of the sorted linked list,
146                     using constant space complexity.
147      */
148     public ListNode sortList(ListNode head) {
149         if (head == null || head.next == null) {
150             return head;
151         }
152         
153         ListNode mid = findMedian(head); // O(n)
154         Pair pair = partition(head, mid.val); // O(n)
155         
156         ListNode left = sortList(pair.first);
157         ListNode right = sortList(pair.second);
158         
159         getTail(left).next = right; // O(n)
160         
161         return left;
162     }
163     
164     // 1->2->3 return 2
165     // 1->2 return 1
166     private ListNode findMedian(ListNode head) {
167         ListNode slow = head, fast = head.next;
168         while (fast != null && fast.next != null) {
169             slow = slow.next;
170             fast = fast.next.next;
171         }
172         return slow;
173     }
174     
175     // < value in the left, > value in the right
176     private Pair partition(ListNode head, int value) {
177         ListNode leftDummy = new ListNode(0), leftTail = leftDummy;
178         ListNode rightDummy = new ListNode(0), rightTail = rightDummy;
179         ListNode equalDummy = new ListNode(0), equalTail = equalDummy;
180         while (head != null) {
181             if (head.val < value) {
182                 leftTail.next = head;
183                 leftTail = head;
184             } else if (head.val > value) {
185                 rightTail.next = head;
186                 rightTail = head;
187             } else {
188                 equalTail.next = head;
189                 equalTail = head;
190             }
191             head = head.next;
192         }
193         
194         leftTail.next = null;
195         rightTail.next = null;
196         equalTail.next = null;
197         
198         if (leftDummy.next == null && rightDummy.next == null) {
199             ListNode mid = findMedian(equalDummy.next);
200             leftDummy.next = equalDummy.next;
201             rightDummy.next = mid.next;
202             mid.next = null;
203         } else if (leftDummy.next == null) {
204             leftTail.next = equalDummy.next;
205         } else {
206             rightTail.next = equalDummy.next;
207         }
208         
209         return new Pair(leftDummy.next, rightDummy.next);
210     }
211     
212     private ListNode getTail(ListNode head) {
213         if (head == null) {
214            return null;
215         } 
216        
217         while (head.next != null) {
218             head = head.next;
219         }
220         return head;
221     }
222 }
原文地址:https://www.cnblogs.com/hygeia/p/5062446.html