[路飞]_程序员必刷力扣题: 148. 排序链表

「这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战

148. 排序链表

给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。 示例 1:

image.png

输入: head = [4,2,1,3]
输出: [1,2,3,4]
复制代码

示例 2:

image.png

输入: 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

};
复制代码

猜你喜欢

转载自juejin.im/post/7054205062553272351