题目描述
在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。
示例
示例1:1
2输入: 4->2->1->3
输出: 1->2->3->4
示例2:1
2输入: -1->5->3->4->0
输出: -1->0->3->4->5
思路
有两种方法:快速排序和归并排序
快速排序的重点和难点是如何根据基准点(这里以头结点为基准)将元素分为两半
归并排序要先利用快慢指针找到中点,根据中点划分为两半,对这两半分别归并排序后,进行合并即可
代码实现
链表节点的定义:1
2
3
4
5
6
7
8class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
}
}
快速排序:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34/**
* 排序范围:从head节点开始,到tail的前一个结点(不包括tail,这样比较好处理)
*/
private void quickSort(ListNode head, ListNode tail) {
if (head == tail || head.next == tail) {
return;
}
int pivot = head.val; //基准值
ListNode center = head;
ListNode curr = head.next;
while (curr != tail) {
if (curr.val < pivot) {
center = center.next;
swap(center, curr);
}
curr = curr.next;
}
//最终在center左边的是比基准值小的
swap(head, center);
quickSort(head, center);
quickSort(center.next, tail);
}
/**
* 交换两节点的值
*/
private void swap(ListNode L1, ListNode L2) {
int temp = L1.val;
L1.val = L2.val;
L2.val = temp;
}
归并排序:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44private ListNode mergeSort(ListNode head) {
if (head == null || head.next == null) {
return head;
}
//先利用快慢指针找到中点
ListNode slow = head;
ListNode fast = head.next;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
ListNode right = mergeSort(slow.next); //排好右半部分
slow.next = null;
ListNode left = mergeSort(head); //排好左半部分
return merge(left, right);
}
/**
* 合并两个已排好序的链表
*/
private ListNode merge(ListNode L1, ListNode L2) {
ListNode dummy = new ListNode(0);
ListNode curr = dummy;
while (L1 != null && L2 != null) {
if (L1.val < L2.val) {
curr.next = L1;
curr = L1;
L1 = L1.next;
} else {
curr.next = L2;
curr = L2;
L2 = L2.next;
}
}
if (L1 != null) {
curr.next = L1;
} else {
curr.next = L2;
}
return dummy.next;
}