「这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战」
148. 排序链表
给你链表的头结点 head
,请将其按 升序 排列并返回 排序后的链表 。 示例 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
归并排序
思路 排序算法中比较高效的如归并,快速,桶排序的时间复杂度为nlogn,适合链表排序的是归并排序。
这里我们用二路归并的思想来做这道题目
首先我们需要将链表均分为两部分,left和right,我们可以使用快慢指针的方式
接着分别对left进行递归处理,递归的终止条件是head为单个节点,对right进行递归处理,得到排序好的sortLeft和sortRight
最后合并sortLeft和sortRight得到最后的结果并返回
具体实现
- 终止条件为head为空或者head.next为null则直接返回
- 通过快慢指针,快指针fast每次走两步既fast.next.next,慢指针走一步slow.next。
left部分为从链表的开头开始,right部分为slow.next开始。并从solw.next=null打断
- 递归处理left和right得到排序的两个子链表
- 合并两个链表,条件是两链表都还有值,一个链表已经全部合并则将剩余的子链表直接拼接上
- 最后返回合并结果
var sortList = function (head) {
// 终止条件
if (!head || !head.next) {
return head
}
//快慢指针寻找中点
var newHead = new ListNode(0, head)
var fast = newHead
var slow = newHead
while (fast && fast.next) {
fast = fast.next.next
slow = slow.next
}
var right = slow.next
slow.next = null
var left = newHead.next
// 递归处理子链表
var sortLeft = sortList(left)
var sortRight = sortList(right)
// 合并排序的子链表
var sortNewHead = new ListNode(0)
var curr = sortNewHead
while (sortLeft && sortRight) {
if (sortLeft.val < sortRight.val) {
curr.next = sortLeft
sortLeft = sortLeft.next
} else {
curr.next = sortRight
sortRight = sortRight.next
}
curr = curr.next
}
if (sortRight) {
curr.next = sortRight
}
if (sortLeft) {
curr.next = sortLeft
}
return sortNewHead.next
};
复制代码