跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

链表分割:以指定值 x 为基准划分链表

链表分割的核心思路是引入两个哨兵节点构建小于 x 和大于等于 x 的两条独立链表。遍历原链表时根据数值大小进行尾插操作,最终合并两条链表并释放哨兵节点。该方法在单次遍历内完成,满足 O(n) 时间复杂度和 O(1) 空间复杂度的要求,且保持了原有节点的相对顺序。

嘘发布于 2026/3/16更新于 2026/9/1660 浏览
链表分割:以指定值 x 为基准划分链表

问题描述

给定一个链表的头指针 pHead 和一个整数值 x,要求将链表分割成两部分。所有小于 x 的结点排在大于或等于 x 的结点之前,且不能改变原来数据的相对顺序。返回分割后的新链表的头指针。

核心要求:

  • 时间复杂度为 O(n)
  • 空间复杂度为 O(1)

思路分析

这道题的核心在于如何高效地重组链表而不破坏原有顺序。如果直接原地修改指针,逻辑会非常复杂,容易出错。比较稳妥的做法是构建两条新的子链表:一条存放小于 x 的节点,另一条存放大于等于 x 的节点。

为了简化边界处理(比如空链表、第一个节点就满足条件等),我们引入两个哨兵节点(Dummy Node)作为虚拟头结点。这样在尾插操作时,无需判断当前是否为头节点,统一由哨兵位接管。

具体步骤如下:

  1. 初始化:创建 guardLess 和 guardGreater 两个哨兵节点,分别对应两条子链表的头部。同时维护两个尾指针 lessTail 和 greaterTail,初始指向各自的哨兵节点。
  2. 遍历:使用移动指针 curNode 扫描原链表。根据节点值与 x 的比较结果,将节点尾插到对应的子链表中,并更新相应的尾指针。
  3. 连接:遍历结束后,将 lessTail->next 指向 guardGreater->next,完成两条链表的拼接。
  4. 收尾:务必将新链表的最后一个节点(即 greaterTail)的 next 置为 nullptr,防止形成环。最后释放哨兵节点内存,返回 guardLess->next 作为新头指针。

代码实现

class Partition {
public:
    ListNode* partition(ListNode* pHead, int x) {
        if (pHead == nullptr) return nullptr;

        // 创建哨兵节点,避免处理头指针为空的情况
        ListNode* guardLess = new ListNode(-1);
        ListNode* guardGreater = new ListNode(-1);

        // 维护两个子链表的尾指针
        ListNode* lessTail = guardLess;
        ListNode* greaterTail = guardGreater;

        ListNode* curNode = pHead;
        while (curNode) {
            if (curNode->val < x) {
                lessTail->next = curNode;
                lessTail = lessTail->next;
            } else {
                greaterTail->next = curNode;
                greaterTail = greaterTail->next;
            }
            curNode = curNode->next;
        }

        // 连接两个链表
        lessTail->next = guardGreater->next;

        // 断开尾部,防止链表带环
        greaterTail->next = nullptr;

        // 保存新链表的头结点
        pHead = guardLess->next;

        // 释放手动开辟的哨兵位头结点
        delete guardGreater;
        delete guardLess;

        return pHead;
    }
};

细节说明

在实际编写时,有几个关键点需要特别注意:

  1. 哨兵位的作用:它让插入逻辑变得统一,不需要单独判断'这是不是第一个节点'。
  2. 断环操作:很多初学者容易忘记 greaterTail->next = nullptr。如果不执行这一步,当原链表最后一个节点被挂到 greater 链表后,它的 next 可能还指向后续节点(虽然遍历结束了,但指针没清),或者如果原链表本身有环,这里必须显式切断以确保安全。
  3. 内存管理:哨兵节点是我们 new 出来的,记得在函数结束前 delete,避免内存泄漏。

这个方案只需要遍历一次链表,逻辑清晰且效率最优,是处理此类链表分区问题的标准解法。

目录

  1. 问题描述
  2. 思路分析
  3. 代码实现
  4. 细节说明

更多推荐文章

查看全部
  • WordPress 基础配置与 Java 后端开发实战笔记
  • DeepSeek 结合通义万相制作 AI 视频实战指南
  • JNI 开发陷阱:C++ Debug 正常为何 Release 返回 NaN
  • 通义千问 2.5-7B-Instruct 模型部署与 AI 写作实战演示
  • 前缀和技巧实战:和为 K 及可被 K 整除的子数组统计
  • AIOps 实践:基于 Dify 与 LangBot 搭建飞书智能体
  • 学术论文 AIGC 检测风险与智能降重工具实战解析
  • C++ 协程深度解析:从内部机制到实用场景
  • Transformer 20 个常见面试问题解析:从基础到高级
  • 扩散模型原理与基于 DDPM 的图像生成实战
  • 前端 Base64 格式文件上传详解:原理、实现与最佳实践
  • MySQL 详细安装配置完整教程
  • C++ 手写线程池:基于策略模式实现日志模块
  • MedReason:利用知识图谱构建大规模医学推理数据集与专家模型
  • llama.cpp 实战指南:在普通电脑上运行大模型
  • AIGC 时代的网络安全威胁与应急响应机制构建
  • TWIST2 全身 VR 遥操系统:基于视觉观测预测关节位置的自主策略
  • Java transient 关键字详解与 Flink State 实践
  • Git 国内镜像源配置指南与跨平台工具开发
  • Flutter OpenHarmony 实战:通义万相 AIGC 联调与相册持久化

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online