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

8.3链表专题:LeetCode 143. 重排链表

链表重排的三大核心操作|快慢指针+逆序+合并详解LeetCode143


1. 题目链接

LeetCode 143. 重排链表


2. 题目描述

给定一个单链表,要求按照「首→尾→次首→次尾」的顺序重新排列节点。要求必须原地修改链表,且不能修改节点值。

示例说明
输入:1 → 2 → 3 → 4
输出:1 → 4 → 2 → 3

输入:1 → 2 → 3 → 4 → 5
输出:1 → 5 → 2 → 4 → 3


3. 示例分析

示例1:偶数长度链表

原始链表:
1 → 2 → 3 → 4
处理过程:

  1. 拆分为前段1→2和后段3→4
  2. 后段逆序为4→3
  3. 交替合并为1→4→2→3

示例2:奇数长度链表

原始链表:
1 → 2 → 3 → 4 → 5
处理过程:

  1. 拆分为前段1→2→3和后段4→5
  2. 后段逆序为5→4
  3. 交替合并为1→5→2→4→3

4. 算法思路

三阶段处理框架

  1. 快慢指针切分链表

    • 慢指针初始指向头节点,快指针初始指向第二个节点(关键设计)
    • 慢指针每次走1步,快指针每次走2步
    • 最终慢指针指向中间节点的前驱节点
  2. 头插法逆序后半段

    原链表:3 → 4 → 5  
    逆序后:5 → 4 → 3
    
  3. 双指针交替合并

    前段指针:1 → 2 → 3  
    后段指针:5 → 4  
    合并结果:1→5→2→4→3
    

5. 边界条件与注意事项

关键边界处理

  1. 短链表特判:长度≤2时直接返回
  2. 奇数长度处理:中间节点归前段
  3. 指针安全防护
    slow->next = nullptr; // 切断前后段联系
    

易错点警示

  1. 快慢指针初始化:快指针初始化为head->next确保中点正确分割
  2. 内存泄漏风险:创建的辅助头节点必须显式释放
  3. 合并顺序错误:必须交替插入前后段节点

6. 代码实现

class Solution {
public:
    void reorderList(ListNode* head) {
        if (!head || !head->next || !head->next->next) return;

        /* 阶段一:快慢指针找中点 */
        ListNode *slow = head, *fast = head->next; // 关键初始化
        while (fast && fast->next) {
            slow = slow->next;
            fast = fast->next->next;
        }

        /* 阶段二:逆序后半段链表 */
        ListNode* head2 = new ListNode(0); // 辅助头节点
        ListNode* cur = slow->next;
        slow->next = nullptr; // 切断前后段
        while (cur) {
            ListNode* next = cur->next;
            cur->next = head2->next;
            head2->next = cur;
            cur = next;
        }

        /* 阶段三:双指针交替合并 */
        ListNode* ret = new ListNode(0); // 虚拟头节点
        ListNode* prev = ret;
        ListNode *cur1 = head, *cur2 = head2->next;
        while (cur1) {
            prev->next = cur1;       // 插入前段节点
            cur1 = cur1->next;
            prev = prev->next;

            if (cur2) {              // 插入后段节点
                prev->next = cur2;
                cur2 = cur2->next;
                prev = prev->next;
            }
        }

        // 内存释放
        delete head2;
        delete ret;
    }
};

关键代码解析

  1. 快慢指针切分

    • 快指针初始指向head->next,确保链表长度为偶数时,慢指针停留在前半段末尾
    • slow->next = nullptr彻底断开前后段联系
  2. 头插法逆序

    • 创建辅助头节点head2简化逆序操作
    • 每次将当前节点插入头节点后,实现逆序
  3. 安全合并

    • 虚拟头节点ret统一处理合并逻辑
    • 交替插入前后段节点,优先处理前段链表

复杂度分析与优化

  • 时间复杂度:O(n)
    三阶段均只需单次遍历链表
  • 空间复杂度:O(1)
    仅使用固定数量的指针变量

优化点:合并阶段可直接复用原链表节点,无需创建新链表,但需注意指针操作顺序。


总结

本解法通过「快慢指针定位→头插法逆序→双指针合并」的三段式处理,以O(n)时间复杂度实现链表重排。
核心技巧

  1. 快慢指针初始值的特殊设置,确保中点分割准确性
  2. 头插法逆序操作的高效实现
  3. 虚拟头节点简化边界条件处理

该解法体现了链表操作中指针控制的精髓,掌握后能应对K个一组翻转等进阶题型。

相关文章:

  • elementui的默认样式修改
  • 常见集合篇(二)数组、ArrayList与链表:原理、源码及业务场景深度解析
  • 【C语言】字符函数的易错点及其模拟实现
  • SQL在线格式化 - 加菲工具
  • WINDOWS 2019 2022 服务器安装了更新补丁 自动重启 分析
  • 第6章 与学习相关的技巧(鱼书)
  • (二)机器学习---常见任务及算法概述
  • 3.31 代码随想录第三十一天打卡
  • 第十章 VGA显示圆
  • # 使用 OpenCV 和神经网络实现图像风格化
  • AISEO中的JSON 如何部署?
  • 为 MinIO AIStor 引入模型上下文协议(MCP)服务器
  • kafka副本同步时HW和LEO
  • Linux驱动开发 中断处理
  • IP-PBX(IP专用交换机)
  • 《HarmonyOS Next开发实战:从零构建响应式Todo应用的基石》
  • 车载以太网网络测试-25【SOME/IP-报文格式-1】
  • RabbitMQ简单介绍和安装
  • OkHttp的拦截器是如何工作的?
  • 【Django】教程-7-分页,默认使用django的
  • 茂名网站制作网页/网站关键词推广
  • 做外汇模拟的网站/培训心得简短
  • 网站建设项目介绍/海外免费网站推广
  • 来返苏州人员信息登记平台/aso榜单优化
  • 求职网站网页设计/上海网络推广公司排名
  • 刷QQ砖的网站咋做/app开发工具哪个好