题目描述
给你链表的头结点 head
,请将其按 升序 排列并返回 排序后的链表 。
进阶:
你可以在 O(n log n)
时间复杂度和常数级空间复杂度下,对链表进行排序吗?
示例 1:
输入:head = [4,2,1,3]
输出:[1,2,3,4]
示例 2:
输入:head = [-1,5,3,4,0]
输出:[-1,0,3,4,5]
示例 3:
输入:head = []
输出:[]
提示:
链表中节点的数目在范围 [0, 5 * 104] 内
-105 <= Node.val <= 105
解题思路
方法一:自上而下归并排序
- 使用归并排序的思路,把链表分成一个一个的两段
- 然后合并这两段链表
- 对链表自顶向下归并排序的过程如下。
- 找到链表的中点,以中点为分界,将链表拆分成两个子链表。寻找链表的中点可以使用快慢指针的做法,快指针每次移动 2 步,慢指针每次移动 1 步,当快指针到达链表末尾时,慢指针指向的链表节点即为链表的中点。
- 对两个子链表分别排序。
- 将两个排序后的子链表合并,得到完整的排序后的链表。可以使用「21. 合并两个有序链表」的做法,将两个有序的子链表进行合并。
复杂度分析
- 时间复杂度:O(nlogn),其中 n 是链表的长度。
- 空间复杂度:O(logn),其中 n 是链表的长度。空间复杂度主要取决于递归调用的栈空间。
js代码
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var sortList = function (head) {
const merge = (list1, list2) => {
let res = new ListNode(0);
let tail = res;
while (list1 && list2) {
if (list1.val < list2.val) {
res.next = list1;
list1 = list1.next;
} else {
res.next = list2;
list2 = list2.next;
}
res = res.next;
}
if (list1) {
res.next = list1;
} else if (list2) {
res.next = list2;
}
return tail.next;
};
const toSortList = (head, tail) => {
if (head === null) {
return head;
}
if (head.next == tail) {
head.next = null;
return head;
}
let fast = (slow = head);
while (fast !== tail && fast.next !== tail) {
fast = fast.next.next;
slow = slow.next;
}
let mid = slow;
return merge(toSortList(head, mid), toSortList(mid, tail));
};
return toSortList(head, null);
};
超过100%提交
思路
- 使用数组存储每一个节点
- 通过数组的sort方法排序
- 通过数组reduce方法,建立数组各元素之间的链表关系
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var sortList = function (head) {
if (!head || !head.next) return head;
let stash = [];
while (head) {
stash.push(head);
const temp = head.next;
head.next = null;
head = temp;
}
stash.sort((a, b) => a.val - b.val).reduce((pre, cur) => (pre.next = cur));
return stash[0];
};