题目
给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。
进阶:
你可以在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序吗?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sort-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
代码
public class Solution {
public ListNode sortList(ListNode head) {
// 递归结束条件
if (head == null || head.next == null) {
return head;
}
// 找到链表中间节点,并断开链表和递归下探(分)
ListNode midNode = middleNode(head);
ListNode rightNode = midNode.next;
midNode.next = null;//断开
ListNode left = sortList(head);
ListNode right = sortList(rightNode);//递归
//合并(治)
return mergeTwoLists(left, right);
}
// 找到链表中点
private ListNode middleNode(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode slow = head;
ListNode fast = head.next.next;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
//合并两个有序链表
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode ans = new ListNode(-1);
ListNode head = ans;
while (l1 != null && l2 != null) {
if (l1.val <= l2.val) {
head.next = l1;
l1 = l1.next;
} else {
head.next = l2;
l2 = l2.next;
}
head = head.next;
}
if (l1 != null) {
head.next = l1;
}
if (l2 != null) {
head.next = l2;
}
return ans.next;
}
}
要点
- 由于是链表,不能使用快排来解决这个问题,故使用分治法
- 按照从底至顶直接合并,先对链表按照中点断开,知道分成只有1个结点,然后合并有序链表
- 寻找链表中点和合并两个有序链表都可以利用之前力扣题的方法