题目链接
排序链表
题目描述
注意点
- 在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序
解答思路
- 使用归并排序对链表进行排序,保证时间复杂度为 O(n log n)
- 相对于数组的归并排序,链表的中间节点需要遍历才能找到,所以需要先找到链表的长度,再根据长度找到中间节点,分别对左右两段链表内部进行排序,内部排序完成后再将两段链表整体进行排序
代码
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode sortList(ListNode head) {
int len = 0;
ListNode node = head;
while (node != null) {
len++;
node = node.next;
}
return mergeList(head, len);
}
private ListNode mergeList(ListNode head, int len) {
if (len <= 1) {
return head;
}
int mid = len / 2;
ListNode tmp = head;
for (int i = 0; i < mid - 1; i++) {
tmp = tmp.next;
}
// 另一段的头节点
ListNode midNode = tmp.next;
// 将两段分割
tmp.next = null;
ListNode node1 = mergeList(head, mid);
ListNode node2 = mergeList(midNode, len - mid);
return merge(node1, node2);
}
private ListNode merge(ListNode node1, ListNode node2) {
ListNode root = new ListNode();
ListNode node = new ListNode();
if (node1.val > node2.val) {
node = node2;
node2 = node2.next;
} else {
node = node1;
node1 = node1.next;
}
root.next = node;
while (node1 != null || node2 != null) {
if (node1 == null) {
node.next = node2;
node2 = node2.next;
node = node.next;
continue;
}
if (node2 == null) {
node.next = node1;
node1 = node1.next;
node = node.next;
continue;
}
if (node1.val > node2.val) {
node.next = node2;
node2 = node2.next;
} else {
node.next = node1;
node1 = node1.next;
}
node = node.next;
}
return root.next;
}
}
关键点
- 归并排序的思想
- 怎样找到两段链表的头节点
- 左边链表的尾节点需要指向空,防止循环链表