题目:
给你链表的头结点 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 ∗ 1 0 4 5 * 10^4 5∗104] 内
- − 1 0 5 -10^5 −105 <= Node.val <= 1 0 5 10^5 105
抛砖引玉
先来一个不讲武德的方法:
用数组存储列表节点排序后再重构链表。
/**
* 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) return head
let node = head,
list = []
while (node) {
list.push(node)
node = node.next
}
list.sort((a, b) => a.val - b.val)
// 重构链表时保留链表头部指针用于返回
let _result = list[0]
_result.next = list[1]
list[list.length - 1].next = null
for (let i = 1; i < list.length - 1; i++) {
list[i].next = list[i + 1]
}
return _result
}
归并排序
将链表递归二分至单个节点,再按照节点大小合并两个二分后的链表
/**
* 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 == null || head.next == null) return head
// 利用快慢指针将链表二分
let fast = head.next,
slow = head
while (fast && fast.next) {
slow = slow.next
fast = fast.next.next
}
// 后一边链表头部指针
let tmp = slow.next
// 分离链表
slow.next = null
// 递归二分值单个节点
let left = sortList(head),
right = sortList(tmp)
// 合并排序的链表
let node = new ListNode(0)
let _result = node
while (left && right) {
if (left.val < right.val) {
node.next = left
left = left.next
} else {
node.next = right
right = right.next
}
node = node.next
}
node.next = left ? left : right
return _result.next
}
博客: 前端小书童
每天的每日一题,写的题解会同步更新到公众号一天一大 lee 栏目
欢迎关注留言