给你链表的头结点
head,请将其按 升序 排列并返回 排序后的链表 。
解法1 暴力解法
思路
先不考虑空间的做法就是将所有节点都放在数组里,然后通过数组排序,最后修改链表指针。
代码
function sortList(head: ListNode | null): ListNode | null {
if (!head || !head.next) {
return head;
}
const nodeList = [];
while (head) {
nodeList.push(head);
head = head.next;
}
nodeList.sort((a, b) => a.val - b.val);
for (let i = 0; i < nodeList.length; i++) {
nodeList[i].next = i === nodeList.length - 1 ? null : nodeList[i + 1];
};
return nodeList[0];
};
时空复杂度
时间复杂度:耗时最多是 sort 排序这里,渐进复杂度为 O(n logn)
空间复杂度:将所有链表都缓存了下来,所以是 O(n)
解法2 分治法
思路
我们可以先借鉴数组的排序,数组的分治就是先分层,然后对每层排序,最后将左右两边排序合并。
链表也可以这样,先通过快慢指针找到中点,然后递归调用找到左右节点,最后返回通过合并的节点。
代码
function sortList(head: ListNode | null): ListNode | null {
if (!head || !head.next) {
return head;
}
let prev = null;
let slow = head;
let fast = head;
while (fast && fast.next) {
prev = slow;
slow = slow.next;
fast = fast.next.next;
}
prev.next = null;
const left = sortList(head);
const right = sortList(slow);
const merge = (left, right) => {
const dummyHead = new ListNode(-1);
let cur = dummyHead;
while (left && right) {
if (left.val < right.val) {
cur.next = left;
left = left.next;
} else {
cur.next = right;
right = right.next;
}
cur = cur.next;
}
cur.next = left ?? right;
return dummyHead.next;
}
return merge(left, right);
};
时空复杂度
时间复杂度:递归的时间复杂度是 O(logn),而每层递归渐进是 O(n),所以总的复杂度是 O(n logn)
空间复杂度:只有递归的栈空间 O(logn)