LeetCode题练习与总结:排序链表--148

news2025/4/5 18:30:51

一、题目描述

给你链表的头结点 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 * 10^4] 内
  • -10^5 <= Node.val <= 10^5

二、解题思路

要解决这个问题,我们可以使用归并排序,这是一种适合链表的排序算法,因为链表的元素在内存中不是连续存储的,归并排序不需要额外的存储空间,且时间复杂度为O(n log n),是一种效率较高的排序算法。

归并排序的基本思想是将链表分成两半,分别对这两半进行排序,然后将排序好的两部分合并在一起。在链表中实现这一思想相对简单,因为只需要改变节点的next指针即可完成排序。

以下是使用归并排序对链表进行排序的步骤:

  1. 找到链表的中点,可以使用快慢指针法。
  2. 将链表从中点断开,形成两个子链表。
  3. 对两个子链表分别进行递归排序。
  4. 将两个已排序的子链表合并在一起。

三、具体代码

class Solution {
    public ListNode sortList(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        // Step 1. 分割链表
        ListNode slow = head, fast = head.next;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        ListNode mid = slow.next;
        slow.next = null;

        // Step 2. 递归排序
        ListNode left = sortList(head);
        ListNode right = sortList(mid);

        // Step 3. 合并链表
        return merge(left, right);
    }

    private ListNode merge(ListNode l1, ListNode l2) {
        ListNode dummy = new ListNode(0);
        ListNode current = dummy;
        while (l1 != null && l2 != null) {
            if (l1.val < l2.val) {
                current.next = l1;
                l1 = l1.next;
            } else {
                current.next = l2;
                l2 = l2.next;
            }
            current = current.next;
        }
        if (l1 != null) {
            current.next = l1;
        } else {
            current.next = l2;
        }
        return dummy.next;
    }
}

四、时间复杂度和空间复杂度

1. 时间复杂度
  • 分割链表:使用快慢指针找到中点的时间复杂度是O(n),其中n是链表的长度。
  • 递归排序:将链表分割成两半,每半的长度大约是n/2,因此递归的深度是O(log n),每次递归调用需要对两个子链表进行合并,合并的时间复杂度是O(n),所以递归排序的总时间复杂度是O(n log n)。
  • 合并链表:合并两个有序链表的时间复杂度是O(n),因为每个节点最多被访问一次。
  • 综上所述,整个算法的时间复杂度是O(n log n)。
2. 空间复杂度
  • 递归栈空间:由于归并排序是递归进行的,所以需要递归栈空间。递归的最大深度是O(log n),每个递归调用需要常数空间,所以递归栈空间的总空间复杂度是O(log n)。
  • 合并链表:合并链表时,除了输入的链表节点外,只需要一个哑节点和几个指针,不需要额外的空间,因此合并链表的空间复杂度是O(1)。
  • 综上所述,整个算法的空间复杂度是O(log n),主要取决于递归栈的空间消耗。

综合以上分析,归并排序链表的算法时间复杂度是O(n log n),空间复杂度是O(log n)。

五、总结知识点

1. 链表的基本操作:

  • 节点构成:链表由节点组成,每个节点包含数据和指向下一个节点的引用。
  • 创建与遍历:链表的创建通过连接节点实现,遍历则是通过依次访问节点的引用。
  • 分割与合并:链表的分割通过调整节点的引用实现,合并则是将两个链表的节点按特定顺序连接。

2. 递归:

  • 函数自调用:递归允许函数调用自身,用于解决可以分解为更小相似问题的大问题。
  • 分治策略:在归并排序中,递归用于将链表分成更小的部分,分别排序后再合并。

3. 快慢指针:

  • 中点查找:快慢指针技术用于找到链表的中点,快指针每次移动两步,慢指针移动一步。
  • 链表分割:当快指针到达链表末尾时,慢指针所指即为链表的中点,从而实现链表的分割。

4. 归并排序:

  • 分治算法:归并排序是一种分治算法,将数据分为两半,分别排序后再合并。
  • 时间复杂度:归并排序的时间复杂度为O(n log n),适用于链表排序。

5. 合并有序链表:

  • 比较与连接:合并两个有序链表时,比较节点值,将较小的节点连接到结果链表中。
  • 链表拼接:当一个链表为空时,将另一个链表的剩余部分接到结果链表的末尾。

6. 哑节点:

  • 辅助节点:哑节点作为辅助节点,用于简化链表操作的边界条件处理。
  • 处理头节点:在合并链表时,使用哑节点作为结果链表的起始节点,避免处理头节点的特殊情况。

以上就是解决这个问题的详细步骤,希望能够为各位提供启发和帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1899768.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

字节码编程javassist之helloworld

写在前面 源码 。 本文一起来看下&#xff0c;如何使用javassist来生成一个helloworld程序。 1&#xff1a;程序 package com.dahuyou.javassist.helloworld;import javassist.*; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; impor…

收银系统源码-营销活动-积分商城

1. 功能描述 营运抽奖&#xff1a;智慧新零售收银系统&#xff0c;线上商城的营销插件&#xff0c;由商户运营&#xff0c;用户通过多种渠道可以获取积分&#xff0c;不仅支持在收银端抵用&#xff0c;还可以在积分商城内兑换优惠券或者真实商品&#xff0c;提升会员活跃度&am…

苹果电脑清理app垃圾高效清理,无需专业知识

在我们的日常使用中&#xff0c;苹果电脑以其优雅的设计和强大的功能赢得了广泛的喜爱。然而&#xff0c;即便是最高效的设备&#xff0c;也无法免俗地积累各种不必要的文件和垃圾&#xff0c;特别是app垃圾。所以&#xff0c;苹果电脑清理app垃圾高效清理&#xff0c;对于大多…

UE5 视频播放(自动播放和自动清除MediaTexture)

媒体播放器的打开时播放和媒体纹理的自动清除 。 在UE5开发视频播放时&#xff0c;遇到了闪帧的现象。合理选择这两个功能可解决。

AE的合成

目录 合成的概念 合成设置 预设 像素长宽比 分辨率​编辑 开始时间码和持续时间 背景颜色 合成的实战理解 在AE的操作界面中&#xff0c;当我们新建了一个项目之后&#xff0c;画面中最主要的位置显示的是新建合成 合成的概念 AE是一款专业特效合成软件&#xff0c;可…

Pandas数据可视化详解:大案例解析(第27天)

系列文章目录 Pandas数据可视化解决不显示中文和负号问题matplotlib数据可视化seaborn数据可视化pyecharts数据可视化优衣库数据分析案例 文章目录 系列文章目录前言1. Pandas数据可视化1.1 案例解析&#xff1a;代码实现 2. 解决不显示中文和负号问题3. matplotlib数据可视化…

昇思25天学习打卡营第18天|Pix2Pix实现图像转换

Pix2Pix概述 Pix2Pix是基于条件生成对抗网络实现的一种深度学习图像转换模型。Pix2Pix是将cGAN应用于有监督的图像到图像翻译&#xff0c;包括生成器和判别器。 基础原理 cGAN的生成器是将输入图片作为指导信息&#xff0c;由输入图像不断尝试生成用于迷惑判别器的“假”图像…

【三】ubuntu24虚拟机集群配置免密登陆

文章目录 环境背景1. 配置域名映射2. 配置免密登录2.1 在每台机器上生成SSH密钥对&#xff1a;2.2 将公钥分发到其他机器&#xff1a;2.2.1 报错问题2.2.2 修复方法 3. 验证免密登录在 ubuntu1 上&#xff1a;在 ubuntu2 上&#xff1a;在 ubuntu3 上&#xff1a; 测试连接 环境…

应急响应-网站入侵篡改指南Webshell内存马查杀漏洞排查时间分析

查看146天的内存马 方法&#xff1a; 1. 日志 这种地址一般在扫描 还要注意post传参注入 对其进行全局定位 发现有sql注入 我们可以也尝试去sqlmap注入 如果以这种方式注入ua头就会改变 2. 了解自己的中间件&#xff0c;框架&#xff0c;cve&#xff0c;等 因为不知道时间…

linux-5.10.110内核源码分析 - Freescale ls1012a pcie host驱动

1、dts pcie设备树 1.1、pcie设备树 pcie1: pcie3400000 {compatible "fsl,ls1012a-pcie";reg <0x00 0x03400000 0x0 0x00100000 /* controller registers */0x40 0x00000000 0x0 0x00002000>; /* configuration space */reg-names "regs", &…

Linux-DNS

DNS域名解析服务 1.DNS介绍 DNS 是域名系统 (Domain Name System) 的缩写&#xff0c;是因特网的一项核心服务&#xff0c;它作为可以将域名和IP地址相互映射的一个分布式数据库&#xff0c;能够使人更方便的访问互联网&#xff0c;而不用去记住能够被机器直接读取的IP数串。…

乐鑫ESPRESSIF芯片开发简介

乐鑫科技&#xff08;Espressif Systems&#xff0c;通常简称乐鑫或ESPRESSIF&#xff09;是一家全球化的无晶圆厂半导体公司&#xff0c;专注于研发无线通信微控制器单元&#xff08;MCU&#xff09;芯片&#xff0c;特别在物联网&#xff08;IoT&#xff09;领域有着显著的影…

【CentOS 7.6】Linux版本 portainer本地镜像导入docker安装配置教程,不需要魔法拉取!(找不着镜像的来看我)

吐槽 我本来根本不想写这篇博客&#xff0c;但我很不解也有点生气&#xff0c;CSDN这么大没有人把现在需要魔法才能拉取的镜像放上来。 你们都不放&#xff0c;根本不方便。我来上传资源。 portainer-ce-latest.tar Linux/amd64 镜像下载地址&#xff1a; 链接&#xff1a;h…

windows下搭建python+jupyter notebook

一.下载python 下面网址下载python3 https://www.python.org/ 二. 安装jupyter notebook 三. 修改配置 四. 检测是否正常运行

【IT领域新生必看】 Java编程中的重写(Overriding)规则:初学者轻松掌握的全方位指南

文章目录 引言什么是方法重写&#xff08;Overriding&#xff09;&#xff1f;方法重写的基本示例 方法重写的规则1. 方法签名必须相同示例&#xff1a; 2. 返回类型可以是子类型&#xff08;协变返回类型&#xff09;示例&#xff1a; 3. 访问修饰符不能比父类的更严格示例&am…

《C++20设计模式》代理模式

文章目录 一、前言二、实现1、UML类图2、实现 一、前言 这代理模式和装饰器模式很像啊。都是套一层类。&#x1f630; 主要就是功能差别 装饰器&#xff1a; 为了强化原有类的功能。代理模式&#xff1a; 不改变原有功能&#xff0c;只是强化原有类的潜在行为。 我觉的书上有…

spark on k8s两种方式的原理与对比

spark on k8s两种方式的原理与对比 1、spark on k8s 方式 spark-submit可以直接用来向 Kubernetes 集群提交 Spark 应用&#xff0c;提交机制如下&#xff1a; 1、Spark 创建一个在Kubernetes pod中运行的 Spark 驱动程序。 2、驱动程序创建在 Kubernetes Pod 中运行的执行器…

Python创建MySQL数据库

一、使用Docker部署本地MySQL数据库 docker run --restartalways -p 3307:3306 --name mysql -e MYSOL_ROOT_PASSWORDlms123456 -d mysql:8.0.25 参数解析: 用户名:root 密码:lms123456 端口:3307 二、在Pycharm开发工具中配置连接MySQL数据库 三、安装zdppy_mysql pip inst…

《向量数据库指南》——Milvus Cloud索引增强如何提升 RAG Pipeline 效果?

索引增强 1.自动合并块 在建立索引时&#xff0c;分两个粒度搭建&#xff0c;一个是chunk本身&#xff0c;另一个是chunk所在的parent chunk。先搜索更细粒度的chunks&#xff0c;接着采用一种合并的策略——如果前k个子chunk中超过n个chunk属于同一个parent chunk&#xff0c…