题目描述
在 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)O(nlogn)和O(1)O(1),根据时间复杂度我们自然想到二分法,从而联想到归并排序;
它是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列。
package leetcode_2;
public class LeetCode148_mergeSortList {
public ListNode sortList(ListNode head) {
if (head == null) {
return null;
}
if (head.next == null) {
return head;
}
ListNode fast = head;
ListNode slow = head;
ListNode slow_pre = null;
while (fast != null && fast.next != null) { //用快慢指针法找中间节点
fast = fast.next.next;
slow_pre = slow;
slow = slow.next;
}
slow_pre.next = null; //左右要断开
ListNode left = sortList(head); //左半段
ListNode right = sortList(slow); //右半段
return merge(left,right);//对已经排好序的左半段和右半段进行合并
}
private ListNode merge(ListNode left, ListNode right) {
ListNode head = new ListNode(0);//虚拟头结点
ListNode p = head;
while (left != null && right != null) {
if (left.val < right.val) {
p.next = left;
left = left.next;
}else {
p.next = right;
right = right.next;
}
p = p.next;
}
if (left != null) {
p.next = left;
}else {
p.next = right;
}
return head.next;
}
public static void main(String[] args) {
ListNode head = new ListNode(-1);
ListNode b = new ListNode(-5);
ListNode c = new ListNode(3);
ListNode d = new ListNode(4);
ListNode e = new ListNode(0);
head.next = b;
b.next = c;
c.next = d;
d.next = e;
LeetCode148_mergeSortList m = new LeetCode148_mergeSortList();
ListNode res = m.sortList(head);
while (res != null) {
System.out.println(res.val);
res = res.next;
}
}
}