版权声明:本文为博主原创文章,转载请注明出处 https://blog.csdn.net/love905661433/article/details/84930685
题目
在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。
示例 1:
输入: 4->2->1->3
输出: 1->2->3->4
示例 2:
输入: -1->5->3->4->0
输出: -1->0->3->4->5
解题
- 链表的特性, 不能随机访问节点
- O(nlogn)级别的算法, 归并排序不需要随机访问节点, 所以可以使用过归并排序解决
- 实际上快速排序也行, 但是快速排序在处理链表问题时, 一方面复杂一点, 一方面性能并没有归并排序高, 下面是归并排序代码:
class Solution {
public ListNode sortList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
return mergeSort(head);
}
/**
* 递归进行归并排序
* @param head
* @return
*/
private ListNode mergeSort(ListNode head) {
if (head.next == null ) {
return head;
}
// 快慢指针
ListNode slow = head;
ListNode fast = head.next;
// 快慢指针查找链表中间节点
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
}
ListNode q = slow.next;
// 截断链表
slow.next = null;
// 递归进行归并排序
ListNode p = mergeSort(head);
q = mergeSort(q);
// 对排序号的链表进行归并
head = merge(p, q);
return head;
}
/**
* 归并
* @param p
* @param q
* @return
*/
private ListNode merge(ListNode p, ListNode q) {
ListNode dummyHead = new ListNode(0);
ListNode cur = dummyHead;
while (p != null || q != null) {
if (p == null) {
cur.next = q;
q = q.next;
} else if (q == null) {
cur.next = p;
p = p.next;
} else {
if (p.val < q.val) {
cur.next = p;
p = p.next;
} else {
cur.next = q;
q = q.next;
}
}
cur = cur.next;
}
return dummyHead.next;
}
}