C++实现LeetCode(143.链表重排序)

发布时间:2026/11/6 9:10:00

C++实现LeetCode(143.链表重排序) 前言LeetCode 第 143 题「重排链表」Reorder List要求把链表L0 → L1 → … → Ln-1 → Ln原地重排为L0 → Ln → L1 → Ln-1 → L2 → Ln-2 → …。题目通常附加一条限制不能只修改节点的值必须真正改变节点的连接关系。这条限制决定了做法。如果允许改值可以把所有值收集到数组里按目标顺序写回节点简单直接但题目要的是指针操作必须把链表「拆开、反转、交错合并」。常见误解是直接用一个数组存节点指针再重连这虽然也改变了连接关系但额外用了 O(n) 空间题目进阶要求 O(1) 额外空间标准解法是「找中点、反转后半、合并两半」。另一个常见错误是找中点后忘记把前半的尾部next置空导致两半仍然相连反转后半时就会把前半也卷进去形成环最后死循环。本文按三步拆解并逐行说明指针顺序。一、把目标拆成三步目标序列可以看成两部分交错前半段L0, L1, L2, …从前往后。后半段Ln, Ln-1, Ln-2, …从后往前。重排就是把后半段反转然后与前半段一个隔一个地合并。于是任务分解为找到链表中点把链表切成两半。反转后半段。把两半交替合并。三步都是链表的基本操作但组合时边界很多节点数为奇数时前半比后半多一个节点数为偶数时两半等长只有一个节点时直接返回合并时不能丢掉任何一截。时间复杂度 O(n)找中点走一遍反转走一遍合并走一遍。空间复杂度 O(1)只用了几个指针。二、找中点与切分用快慢指针找中点slow每次走一步fast每次走两步。循环条件是fast-next ! nullptr fast-next-next ! nullptr。这个条件让slow最终停在「前半段的最后一个节点」n 为奇数例如 5 个节点slow停在下标 2中间节点前半是 0..2后半是 3..4。n 为偶数例如 4 个节点slow停在下标 1前半是 0..1后半是 2..3。无论奇偶后半段长度都不超过前半段这为后面的合并循环提供了便利。找到中点后先保存second slow-next再执行slow-next nullptr。这一步是切分必须做。若不切前半的尾节点仍然指向后半的头反转后半时会沿着这条边把前半也串进来合并时两半互相指向很快形成环程序可能陷入死循环或输出错乱。切分后前半以head开头、slow结尾后半以second开头。此时两条链表互不相连。三、反转后半与交替合并反转用三指针prev、cur、next。每次先保存cur-next再让cur-next prev然后推进prev和cur。循环结束时prev是反转后的头。这部分与普通链表反转完全相同注意不要先改cur-next再保存后继。合并时first指向前半当前节点second指向后半当前节点。每一轮保存firstNext first-next。保存secondNext second-next。first-next second;second-next firstNext;first firstNext;second secondNext;循环条件是second ! nullptr。因为后半不长于前半后半走完时前半要么刚好走完要么还剩最后一个节点这个节点已经在前一轮被second-next firstNext接上不需要额外处理。若循环条件写成first ! nullptr second ! nullptr当后半先空时也能退出但若前半先空理论上不会因为后半不长于前半就会解引用空指针。用second作为条件最稳。第 1、2 步的保存不能省。第 3 步会覆盖first-next第 4 步会覆盖second-next如果不提前保存下一轮就找不到两条链表的后续节点链表会被截断。四、完整实现// 适用于 C17#include iostreamstruct ListNode {int val;ListNode* next;ListNode() : val(0), next(nullptr) {}ListNode(int x) : val(x), next(nullptr) {}ListNode(int x, ListNode* next) : val(x), next(next) {}};void reorderList(ListNode* head) {if (head nullptr || head-next nullptr) {return;}// 1. 快慢指针找中点slow 停在前半的最后一个节点ListNode* slow head;ListNode* fast head;while (fast-next ! nullptr fast-next-next ! nullptr) {slow slow-next;fast fast-next-next;}// 2. 切分并反转后半ListNode* second slow-next;slow-next nullptr;ListNode* prev nullptr;while (second ! nullptr) {ListNode* next second-next;second-next prev;prev second;second next;}second prev;// 3. 交替合并两半ListNode* first head;while (second ! nullptr) {ListNode* firstNext first-next;ListNode* secondNext second-next;first-next second;second-next firstNext;first firstNext;second secondNext;}}void printList(const ListNode* head) {for (const ListNode* p head; p ! nullptr; p p-next) {std::cout p-val ;}std::cout \n;}int main() {ListNode* head new ListNode(1);head-next new ListNode(2);head-next-next new ListNode(3);head-next-next-next new ListNode(4);head-next-next-next-next new ListNode(5);reorderList(head);printList(head); // 按定义应为 1 5 2 4 3while (head ! nullptr) {ListNode* next head-next;delete head;head next;}return 0;}以 1、2、3、4、5 为例slow停在中点 3前半是 1→2→3后半是 4→5反转后变成 5→4合并得到 1→5→2→4→3。若节点数是 4前半 1→2后半 3→4反转后 4→3合并得到 1→4→2→3也符合「首、尾、次首、次尾」的规律。main里手动new了五个节点最后逐个delete是为了演示完整的所有权LeetCode 的判题环境会统一回收不需要在函数里释放。真实工程中更推荐用std::unique_ptr管理节点或在reorderList之外用容器持有节点。常见坑点1. 只交换节点的值❌ 用数组收集值再按目标顺序写回val。✅ 题目要求改变连接关系按「找中点、反转、合并」操作指针。2. 忘记切断两半❌ 找到中点后直接反转slow-next开始的链表不置空slow-next。✅second slow-next; slow-next nullptr;再反转。3. 反转时先改指针再保存后继❌cur-next prev; next cur-next;next拿到的是prev。✅ 先next cur-next;再改指向。4. 合并时丢失后半的后续❌ 只保存firstNext不保存secondNextsecond-next被覆盖后找不到下一段。✅ 两个next都要在覆盖前保存。5. 合并循环条件写错❌while (first ! nullptr)前半走完后解引用空指针。✅while (second ! nullptr)后半不长于前半天然安全。6. 中点条件写成fast ! nullptr fast-next ! nullptr❌slow停在中间偏右后半长度可能大于前半合并时前半先空。✅ 用fast-next ! nullptr fast-next-next ! nullptr让slow停在前半末尾。7. 空表或单节点没处理❌ 直接进入找中点head-next为空时仍访问head-next-next。✅ 入口判断head nullptr || head-next nullptr直接返回。8. 认为必须新建节点❌ 为每个值new ListNode再拼接。✅ 原地改next空间 O(1)不新建节点。总结步骤操作关键点找中点快慢指针slow停在前半末尾切分slow-next nullptr必须断开防止成环反转后半三指针先存后继再改指向合并交替接链保存两个next时间O(n)三遍扫描空间O(1)只用指针边界空表、单节点直接返回链表重排序的解法可以背成三句话快慢指针找中点并切断反转后半交替合并。真正容易出错的是「切断」和「保存后继」这两个动作——它们不改变算法框架却决定了链表会不会成环、会不会丢节点。把这两处写对奇偶长度的差异就会被循环条件自然吸收。
延伸阅读

更多相关文章

2026/11/6 9:10:00

具身智能技术解析:从多模态感知到商业化落地

1. 项目背景与行业定位 "魔法原子"这个命名本身就充满想象力,它让我联想到科幻作品中那些能够重构物质的基础单元。而105亿这个数字,在当前具身智能领域的融资规模中确实属于头部梯队。具身智能(Embodied AI)作为AI发展…

2026/11/6 9:10:00

Sentry MCP Server:AI调试与错误追踪工具解析

1. Sentry MCP Server:AI调试利器深度解析在软件开发过程中,错误追踪和调试是每个工程师的日常必修课。Sentry MCP Server作为一款专为AI调试设计的工具,能够自动获取错误堆栈、追踪问题,让Bug无处遁形。这个工具虽然已被官方归档…

2026/11/6 9:10:00

2025年学术论文引用工具评测与自动化引用指南

1. 论文引用工具的核心价值与选择逻辑 写论文最头疼的环节是什么?十有八九的学术党会告诉你:参考文献格式。APA、MLA、Chicago、GB/T 7714...不同期刊要求各异,手动调整一个标点符号都能让人崩溃。我帮导师审稿时见过最夸张的案例&#xff1a…

2026/11/6 9:55:13

实战分享:Docker镜像构建优化技巧(进阶篇)全流程解析

本文深入探讨Docker镜像构建优化技巧(进阶篇),涵盖背景分析、原理剖析、实战步骤、配置示例、优化建议和避坑指南。随着业务规模增长,Docker镜像构建优化技巧(进阶篇)的重要性日益凸显。无论你是刚入门还是…

2026/11/6 9:55:13

GitOps工作流实践指南(进阶篇)——工程师必备知识

本文深入探讨GitOps工作流实践指南(进阶篇),涵盖背景分析、原理剖析、实战步骤、配置示例、优化建议和避坑指南。作为DevOps与运维从业者,掌握GitOps工作流实践指南(进阶篇)不仅能提升系统稳定性&#xff0…

2026/11/6 9:55:13

Kubernetes HPA自动扩缩容(进阶篇)最佳实践与踩坑记录

本文深入探讨Kubernetes HPA自动扩缩容(进阶篇),涵盖背景分析、原理剖析、实战步骤、配置示例、优化建议和避坑指南。作为DevOps与运维从业者,掌握Kubernetes HPA自动扩缩容(进阶篇)不仅能提升系统稳定性&a…

2026/11/6 9:40:08

Windows域控 设置全域的密码策略 【全域策略生效】

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/6 9:40:08

Spring+SpringMVC+MyBatis 整合(+拦截器) 详:

SpringSpringMVCMyBatis 整合(拦截器) 详: 目前为止博客基本已将掌握SpringMVC 相关的知识点; 终于来到了最终时刻 SSM 三大框架整合; 搭建SSM 框架的程序架构 SSM 框架整合其实就是:Mybatis Spring SpringMVC 的整合; 前面学习我们知道 &#xff1a…

2026/11/5 15:39:06

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/4 21:04:25

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/6 1:03:39

MCU晶振电路设计全解析:从负载电容计算到PCB布局调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 15:39:06

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/4 21:04:25

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑