148. Sort List
题目
原始地址:https://leetcode.com/problems/sort-list/#/description
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
public class Solution {
public ListNode sortList(ListNode head) {
}
}
描述
排序一个链表,要求时间复杂度为O(nlogn),空间复杂度为常量。
分析
链表排序不同于数组排序,数组排序可以通过索引访问而链表不可以。常见排序算法中时间复杂度能达到O(nlogn)的只有快速排序、希尔排序和归并排序,而其中不使用索引访问的就只剩下归并排序了。
我们先通过使用快慢指针的方式找到链表中心并将其分为两个子链表,注意此时要将两个子链表断开。之后递归调用该方法排序两个子链表,分别完成后再做归并即可。
解法
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
public class Solution {
public ListNode sortList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode fast = head, slow = head;
while (fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
fast = slow.next;
slow.next = null;
head = sortList(head);
fast = sortList(fast);
return merge(head, fast);
}
private ListNode merge(ListNode l1, ListNode l2) {
ListNode head = new ListNode(0), curr = head;
while (l1 != null && l2 != null) {
if (l1.val < l2.val) {
curr.next = l1;
l1 = l1.next;
} else {
curr.next = l2;
l2 = l2.next;
}
curr = curr.next;
}
if (l1 == null) {
curr.next = l2;
} else {
curr.next = l1;
}
return head.next;
}
}