Q:在O(n log n)的时间内使用常数级空间复杂度对链表进行排序。
A:
1.用sort,这样做……可以过,但很讨巧,不大好
public ListNode sortList(ListNode head) {
if (head == null)
return head;
List<Integer> list = new ArrayList<>();
ListNode node = head;
while (node != null) {
list.add(node.val);
node = node.next;
}
Collections.sort(list);
ListNode head1 = new ListNode(list.get(0));
ListNode node1 = head1;
for (int i = 1; i < list.size(); i++) {
ListNode node2 = new ListNode(list.get(i));
node1.next = node2;
node1 = node1.next;
}
return head1;
}
2.排序算法:只有堆排序(用PriorityQueue)和归并排序。不过我很奇怪,如果用递归,空间复杂度不就不符合了吗?
数组存储的归并排序 时间复杂度O(nlogn)空间复杂度 O(n)
链表存储的归并排序 时间复杂度O(nlogn)空间复杂度 O(1)
public ListNode sortList(ListNode head) {
//一定不要忘了head.next == null,要不到时候都是null
if (head == null || head.next == null)
return head;
ListNode mid = getMid(head);
ListNode midNest = mid.next;
mid.next = null;
ListNode left = sortList(head);
ListNode right = sortList(midNest);
return merge(left, right);
}
public static ListNode getMid(ListNode head) {
if (head == null || head.next == null)
return head;
ListNode slow = head;
ListNode fast = head.next;
while (fast.next != null && fast.next.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
public static ListNode merge(ListNode left, ListNode right) {
if (left == null)
return right;
if (right == null)
return left;
ListNode head;
if (left.val <= right.val) {
head = left;
left = left.next;
head.next = null;
} else {
head = right;
right = right.next;
head.next = right;
}
ListNode newNode = head;
while (left != null && right != null) {
if (left.val <= right.val) {
newNode.next = left;
left = left.next;
newNode = newNode.next;
newNode.next = null;
} else {
newNode.next = right;
right = right.next;
newNode = newNode.next;
newNode.next = null;
}
}
if (left != null)
newNode.next = left;
if (right != null)
newNode.next = right;
return head;
}