当前位置: 首页 > article >正文

LeetCode - 148. 排序链表

目录

题目

思路

基本情况检查

复杂度分析

执行示例

读者可能出的错误

正确的写法 


题目

148. 排序链表 - 力扣(LeetCode)

思路

链表归并排序采用"分治"的策略,主要分为三个步骤:

  1. 分割:将链表从中间分成两个子链表
  1. 排序:递归地对两个子链表进行排序
  1. 合并:将两个已排序的子链表合并为一个有序链表

基本情况检查

if (!head || !head->next) return head;
  • 如果链表为空或只有一个节点,已经是有序的,直接返回

找到链表中点

ListNode* slow = head;
ListNode* fast = head->next;while (fast && fast->next) {slow = slow->next;fast = fast->next->next;
}
  • 使用快慢指针法找到链表中点
  • slow指针每次移动一步,fast指针每次移动两步
  • 当fast到达链表末尾时,slow指向链表的中间位置(偶数长度链表时指向前半部分的最后一个节点)

 分割链表

ListNode* mid = slow->next;
slow->next = nullptr;
  • mid指向后半部分的第一个节点
  • 将slow->next设为nullptr,切断链表,得到两个独立的子链表

 递归排序

ListNode* left = sortList(head);
ListNode* right = sortList(mid);
  • 递归地对前半部分和后半部分分别进行排序
  • 递归将继续分割链表直到子链表长度为1

 合并有序链表

return merge(left, right);
  • 将两个已排序的子链表合并成一个有序链表

 合并函数实现

ListNode* merge(ListNode* l1, ListNode* l2) {ListNode dummy(0);ListNode* curr = &dummy;while (l1 && l2) {if (l1->val <= l2->val) {curr->next = l1;l1 = l1->next;} else {curr->next = l2;l2 = l2->next;}curr = curr->next;}curr->next = l1 ? l1 : l2;return dummy.next;
}
  • 创建一个虚拟头节点dummy简化边界情况处理
  • 逐个比较两个链表的节点,将较小的节点连接到结果链表
  • 当一个链表为空时,将另一个链表的剩余部分直接连接到结果链表

执行示例

复杂度分析

时间复杂度:O(n log n)

  • 分割链表:每次将链表分成两半,需要O(log n)次分割
  • 每层合并操作:需要O(n)时间

总体时间复杂度:O(n log n)

  • 空间复杂度:O(log n)
  • 由于递归调用栈的深度为O(log n)

读者可能出的错误写法

class Solution {
public:ListNode* sortList(ListNode* head) {ListNode* slow = head;ListNode* fast = head;while(head->next){slow = slow->next;fast = fast->next->next;}ListNode* mid = slow;slow->next = nullptr;ListNode* left = sortList(head);ListNode* right = sortList(mid);return merge(head,mid);}
private:ListNode* merge(ListNode* l1,ListNode*l2){ListNode* dummy = new ListNode(0);ListNode* current = dummy;while(l1 && l2){if(l1->val <= l2->val){current->next = l1;l1=l1->next;}else{current->next = l2;l2=l2->next;}}while(l1||l2){if(l1){current->next = l1;}if(l2){current->next = l2;}}return dummy;}};

无终止条件:缺少递归的基本情况检查,如果head为空或只有一个节点,应该直接返回

快慢指针初始化问题:你的fast和slow都从head开始,但标准做法是slow从head开始,fast从head->next开始

无效的循环条件:你的循环条件是while(head->next),这不会移动,会导致无限循环。应该是while(fast && fast->next)

链表分割问题:

  • 当链表长度为2时,slow和mid会指向同一个节点,导致无限递归
  • 应该让mid = slow->next,然后将slow->next = nullptr来正确分割链表

错误的递归参数:在递归调用时,你返回的是merge(head, mid),但应该是merge(left, right)

merge函数中的问题:

在处理剩余节点时,你的循环条件是while(l1||l2),但在循环体内没有更新current指针,会导致无限循环

你没有正确处理一个链表为空的情况

内存泄漏:创建了dummy节点但没有释放,应该返回dummy->next并释放dummy

    正确的写法 

    class Solution {
    public:ListNode* sortList(ListNode* head) {// 基本情况:空链表或只有一个节点if (!head || !head->next) {return head;}// 1. 使用快慢指针找到链表中点ListNode* slow = head;ListNode* fast = head->next;while (fast && fast->next) {slow = slow->next;      // 慢指针每次移动一步fast = fast->next->next; // 快指针每次移动两步}// 此时slow指向中间节点的前一个节点ListNode* mid = slow->next; // mid是后半部分的起始节点slow->next = nullptr;       // 断开链表// 2. 递归排序两个子链表ListNode* left = sortList(head); // 排序前半部分ListNode* right = sortList(mid);  // 排序后半部分// 3. 合并两个有序链表return merge(left, right);}private:// 合并两个有序链表ListNode* merge(ListNode* l1, ListNode* l2) {// 创建虚拟头节点,简化边界情况处理ListNode dummy(0);ListNode* curr = &dummy;// 比较两个链表的节点值,将较小的节点添加到结果链表while (l1 && l2) {if (l1->val <= l2->val) {curr->next = l1;l1 = l1->next;} else {curr->next = l2;l2 = l2->next;}curr = curr->next;}// 连接剩余部分(如果有)curr->next = l1 ? l1 : l2;return dummy.next;}
    };

    相关文章:

    LeetCode - 148. 排序链表

    目录 题目 思路 基本情况检查 复杂度分析 执行示例 读者可能出的错误 正确的写法 题目 148. 排序链表 - 力扣&#xff08;LeetCode&#xff09; 思路 链表归并排序采用"分治"的策略&#xff0c;主要分为三个步骤&#xff1a; 分割&#xff1a;将链表从中间…...

    多模态大语言模型arxiv论文略读(110)

    CoVLA: Comprehensive Vision-Language-Action Dataset for Autonomous Driving ➡️ 论文标题&#xff1a;CoVLA: Comprehensive Vision-Language-Action Dataset for Autonomous Driving ➡️ 论文作者&#xff1a;Hidehisa Arai, Keita Miwa, Kento Sasaki, Yu Yamaguchi, …...

    React、Git、计网、发展趋势等内容——前端面试宝典(字节、小红书和美团)

    React React Hook实现架构、.Hook不能在循环嵌套语句中使用 , 为什么&#xff0c;Fiber架构&#xff0c;面试向面试官介绍&#xff0c;详细解释 用户: React Hook实现架构、.Hook不能在循环嵌套语句中使用 , 为什么&#xff0c;Fiber架构&#xff0c;面试向面试官介绍&#x…...

    Web APIS Day01

    1.声明变量const优先 那为什么一开始前面就不能用const呢&#xff0c;接下来看几个例子&#xff1a; 下面这张为什么可以用const呢&#xff1f;因为复杂数据的引用地址没变&#xff0c;数组还是数组&#xff0c;只是添加了个元素&#xff0c;本质没变&#xff0c;所以可以用con…...

    关于 ffmpeg设置摄像头报错“Could not set video options” 的解决方法

    若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/148515355 长沙红胖子Qt&#xff08;长沙创微智科&#xff09;博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV…...

    Linux系统:进程间通信-匿名与命名管道

    本节重点 匿名管道的概念与原理匿名管道的创建命名管道的概念与原理命名管道的创建两者的差异与联系命名管道实现EchoServer 一、管道 管道&#xff08;Pipe&#xff09;是一种进程间通信&#xff08;IPC, Inter-Process Communication&#xff09;机制&#xff0c;用于在不…...

    使用python进行图像处理—图像变换(6)

    图像变换是指改变图像的几何形状或空间位置的操作。常见的几何变换包括平移、旋转、缩放、剪切&#xff08;shear&#xff09;以及更复杂的仿射变换和透视变换。这些变换在图像配准、图像校正、创建特效等场景中非常有用。 6.1仿射变换(Affine Transformation) 仿射变换是一种…...

    使用homeassistant 插件将tasmota 接入到米家

    我写一个一个 将本地tasmoat的的设备同通过ha集成到小爱同学的功能&#xff0c;利用了巴法接入小爱的功能&#xff0c;将本地mqtt转发给巴法以实现小爱控制的功能&#xff0c;前提条件。1需要tasmota 设备&#xff0c; 2.在本地搭建了mqtt服务可&#xff0c; 3.搭建了ha 4.在h…...

    VUE3 ref 和 useTemplateRef

    使用ref来绑定和获取 页面 <headerNav ref"headerNavRef"></headerNav><div click"showRef" ref"buttonRef">refbutton</div>使用ref方法const后面的命名需要跟页面的ref值一样 const buttonRef ref(buttonRef) cons…...

    【笔记】结合 Conda任意创建和配置不同 Python 版本的双轨隔离的 Poetry 虚拟环境

    如何结合 Conda 任意创建和配置不同 Python 版本的双轨隔离的Poetry 虚拟环境&#xff1f; 在 Python 开发中&#xff0c;为不同项目配置独立且适配的虚拟环境至关重要。结合 Conda 和 Poetry 工具&#xff0c;能高效创建不同 Python 版本的 Poetry 虚拟环境&#xff0c;接下来…...

    多模态学习路线(2)——DL基础系列

    目录 前言 一、归一化 1. Layer Normalization (LN) 2. Batch Normalization (BN) 3. Instance Normalization (IN) 4. Group Normalization (GN) 5. Root Mean Square Normalization&#xff08;RMSNorm&#xff09; 二、激活函数 1. Sigmoid激活函数&#xff08;二分类&…...

    [10-1]I2C通信协议 江协科技学习笔记(17个知识点)

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17...

    AWSLambda之设置时区

    目标 希望Lambda运行的时区是东八区。 解决 只需要设置lambda的环境变量TZ为东八区时区即可&#xff0c;即Asia/Shanghai。 参考 使用 Lambda 环境变量...

    RFID推动新能源汽车零部件生产系统管理应用案例

    RFID推动新能源汽车零部件生产系统管理应用案例 一、项目背景 新能源汽车零部件场景 在新能源汽车零部件生产领域&#xff0c;电子冷却水泵等关键部件的装配溯源需求日益增长。传统 RFID 溯源方案采用 “网关 RFID 读写头” 模式&#xff0c;存在单点位单独头溯源、网关布线…...

    [C++错误经验]case语句跳过变量初始化

    标题&#xff1a;[C错误经验]case语句跳过变量初始化 水墨不写bug 文章目录 一、错误信息复现二、错误分析三、解决方法 一、错误信息复现 write.cc:80:14: error: jump to case label80 | case 2:| ^ write.cc:76:20: note: crosses initialization…...

    Unity-ECS详解

    今天我们来了解Unity最先进的技术——ECS架构&#xff08;EntityComponentSystem&#xff09;。 Unity官方下有源码&#xff0c;我们下载源码后来学习。 ECS 与OOP&#xff08;Object-Oriented Programming&#xff09;对应&#xff0c;ECS是一种完全不同的编程范式与数据架构…...

    uni-app学习笔记二十七--设置底部菜单TabBar的样式

    官方文档地址&#xff1a;uni.setTabBarItem(OBJECT) | uni-app官网 uni.setTabBarItem(OBJECT) 动态设置 tabBar 某一项的内容&#xff0c;通常写在项目的App.vue的onLaunch方法中&#xff0c;用于项目启动时立即执行 重要参数&#xff1a; indexnumber是tabBar 的哪一项&…...

    7种分类数据编码技术详解:从原理到实战

    在数据分析和机器学习领域&#xff0c;分类数据&#xff08;Categorical Data&#xff09;的处理是一个基础但至关重要的环节。分类数据指的是由有限数量的离散值组成的数据类型&#xff0c;如性别&#xff08;男/女&#xff09;、颜色&#xff08;红/绿/蓝&#xff09;或产品类…...

    【字节拥抱开源】字节团队开源视频模型 ContentV: 有限算力下的视频生成模型高效训练

    本项目提出了ContentV框架&#xff0c;通过三项关键创新高效加速基于DiT的视频生成模型训练&#xff1a; 极简架构设计&#xff0c;最大化复用预训练图像生成模型进行视频合成系统化的多阶段训练策略&#xff0c;利用流匹配技术提升效率经济高效的人类反馈强化学习框架&#x…...

    本地部署drawDB结合内网穿透技术实现数据库远程管控方案

    文章目录 前言1. Windows本地部署DrawDB2. 安装Cpolar内网穿透3. 实现公网访问DrawDB4. 固定DrawDB公网地址 前言 在数字化浪潮席卷全球的背景下&#xff0c;数据治理能力正日益成为构建现代企业核心竞争力的关键因素。无论是全球500强企业的数据中枢系统&#xff0c;还是初创…...

    可视化预警系统:如何实现生产风险的实时监控?

    在生产环境中&#xff0c;风险无处不在&#xff0c;而传统的监控方式往往只能事后补救&#xff0c;难以做到提前预警。但如今&#xff0c;可视化预警系统正在改变这一切&#xff01;它能够实时收集和分析生产数据&#xff0c;通过直观的图表和警报&#xff0c;让管理者第一时间…...

    多模态大语言模型arxiv论文略读(112)

    Assessing Modality Bias in Video Question Answering Benchmarks with Multimodal Large Language Models ➡️ 论文标题&#xff1a;Assessing Modality Bias in Video Question Answering Benchmarks with Multimodal Large Language Models ➡️ 论文作者&#xff1a;Jea…...

    【向量库】Weaviate概述与架构解析

    文章目录 一、什么是weaviate二、High-Level Architecture1. Core Components2. Storage Layer3. 组件交互流程 三、核心组件1. API Layer2. Schema Management3. Vector Indexing3.1. 查询原理3.2. 左侧&#xff1a;Search Process&#xff08;搜索流程&#xff09;3.3. 右侧&…...

    PostgreSQL 对 IPv6 的支持情况

    PostgreSQL 对 IPv6 的支持情况 PostgreSQL 全面支持 IPv6 网络协议&#xff0c;包括连接、存储和操作 IPv6 地址。以下是详细说明&#xff1a; 一、网络连接支持 1. 监听 IPv6 连接 在 postgresql.conf 中配置&#xff1a; listen_addresses 0.0.0.0,:: # 监听所有IPv4…...

    python数据结构和算法(1)

    数据结构和算法简介 数据结构&#xff1a;存储和组织数据的方式&#xff0c;决定了数据的存储方式和访问方式。 算法&#xff1a;解决问题的思维、步骤和方法。 程序 数据结构 算法 算法 算法的独立性 算法是独立存在的一种解决问题的方法和思想&#xff0c;对于算法而言&a…...

    视觉slam--框架

    视觉里程计的框架 传感器 VO--front end VO的缺点 后端--back end 后端对什么数据进行优化 利用什么数据进行优化的 后端是怎么进行优化的 回环检测 建图 建图是指构建地图的过程。 构建的地图是点云地图还是什么信息的地图&#xff1f; 建图并没有一个固定的形式和算法…...

    统计按位或能得到最大值的子集数目

    我们先来看题目描述&#xff1a; 给你一个整数数组 nums &#xff0c;请你找出 nums 子集 按位或 可能得到的 最大值 &#xff0c;并返回按位或能得到最大值的 不同非空子集的数目 。 如果数组 a 可以由数组 b 删除一些元素&#xff08;或不删除&#xff09;得到&#xff0c;…...

    npm install 相关命令

    npm install 相关命令 基本安装命令 # 安装 package.json 中列出的所有依赖 npm install npm i # 简写形式# 安装特定包 npm install <package-name># 安装特定版本 npm install <package-name><version>依赖类型选项 # 安装为生产依赖&#xff08;默认&…...

    Spring Boot 与 Kafka 的深度集成实践(二)

    3. 生产者实现 3.1 生产者配置 在 Spring Boot 项目中&#xff0c;配置 Kafka 生产者主要是配置生产者工厂&#xff08;ProducerFactory&#xff09;和 KafkaTemplate 。生产者工厂负责创建 Kafka 生产者实例&#xff0c;而 KafkaTemplate 则是用于发送消息的核心组件&#x…...

    【学习记录】使用 Kali Linux 与 Hashcat 进行 WiFi 安全分析:合法的安全测试指南

    文章目录 &#x1f4cc; 前言&#x1f9f0; 一、前期准备✅ 安装 Kali Linux✅ 获取支持监听模式的无线网卡 &#x1f6e0; 二、使用 Kali Linux 进行 WiFi 安全测试步骤 1&#xff1a;插入无线网卡并确认识别步骤 2&#xff1a;开启监听模式步骤 3&#xff1a;扫描附近的 WiFi…...