LeetCode-热题100: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

代码及注释

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */

func sortList(head *ListNode) *ListNode {
    // 边界情况:链表为空或只有一个节点时,直接返回
    if head == nil || head.Next == nil {
        return head
    }

    // 使用快慢指针找到链表的中点
    slow, fast := head, head
    var cur *ListNode
    for fast != nil && fast.Next != nil {
        cur = slow
        slow = slow.Next
        fast = fast.Next.Next
    }

    // 断开链表,将链表分为两部分
    cur.Next = nil

    // 递归地对左右两部分进行排序
    l := sortList(head)
    r := sortList(slow)

    // 合并两个有序链表
    return merge(l, r)
}

func merge(l1 *ListNode, l2 *ListNode) *ListNode {
    // 使用哑节点简化代码
    var dummy = &ListNode{}
    cur := dummy

    // 循环比较两个链表的节点,并将较小的节点连接到新链表中
    for l1 != nil && l2 != nil {
        if l1.Val > l2.Val {
            cur.Next = l2
            l2 = l2.Next
        } else {
            cur.Next = l1
            l1 = l1.Next
        }
        cur = cur.Next
    }

    // 将剩余的节点连接到新链表的末尾
    if l1 != nil {
        cur.Next = l1
    } else {
        cur.Next = l2
    }

    // 返回合并后的链表
    return dummy.Next
}

代码解释

sortList 函数

  1. 终止条件

    if head == nil || head.Next == nil {
        return head
    }
    

    当链表为空或只有一个节点时,无需排序,直接返回。

  2. 找到中点

    slow, fast := head, head
    var cur *ListNode
    for fast != nil && fast.Next != nil {
        cur = slow
        slow = slow.Next
        fast = fast.Next.Next
    }
    cur.Next = nil
    

    使用快慢指针找到链表的中点,并将链表断开,得到两个子链表 lr

  3. 递归排序

    l := sortList(head)
    r := sortList(slow)
    

    使用递归对左右两个子链表进行排序。

  4. 合并两个排序后的子链表

    return merge(l, r)
    

    调用 merge 函数合并两个排序后的子链表。

merge 函数

  1. 初始化

    var dummy = &ListNode{}
    cur := dummy
    

    使用哑节点 dummycur 指针来合并两个链表。

  2. 比较合并

    for l1 != nil && l2 != nil {
        if l1.Val > l2.Val {
            cur.Next = l2
            l2 = l2.Next
        } else {
            cur.Next = l1
            l1 = l1.Next
        }
        cur = cur.Next
    }
    

    比较 l1l2 的当前节点值,将较小的节点连接到 cur.Next

  3. 处理剩余节点

    if l1 != nil {
        cur.Next = l1
    } else {
        cur.Next = l2
    }
    

    将剩余的 l1l2 链接到 cur.Next

相关推荐

  1. LeetCode100】【排序

    2024-04-12 01:38:02       129 阅读
  2. LeetCode 100 | (下)

    2024-04-12 01:38:02       54 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-12 01:38:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-12 01:38:02       100 阅读
  3. 在Django里面运行非项目文件

    2024-04-12 01:38:02       82 阅读
  4. Python语言-面向对象

    2024-04-12 01:38:02       91 阅读

热门阅读

  1. 工业通信原理——CRC校验

    2024-04-12 01:38:02       38 阅读
  2. std::unordered_map 自定义hash,key-value

    2024-04-12 01:38:02       33 阅读
  3. Unity抛物线目标点打击

    2024-04-12 01:38:02       36 阅读
  4. Gitea的简单介绍

    2024-04-12 01:38:02       35 阅读
  5. ClickHouse入门篇:一文带你学习ClickHouse

    2024-04-12 01:38:02       28 阅读
  6. ChatGPT智能写作:开启论文写作新视野

    2024-04-12 01:38:02       41 阅读
  7. PCA 主成分分析

    2024-04-12 01:38:02       32 阅读