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

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

链表分割问题要求以给定值 x 为基准将链表划分为小于 x 和大于等于 x 的两部分,并保持原数据相对顺序。解决方案采用双哨兵头结点策略,在一次遍历中通过尾插法完成分区,随后连接两段链表。该方法时间复杂度为 O(n),空间复杂度为 O(1)。实现时需特别注意断开尾指针以防止成环,并及时释放哨兵节点内存。

CodeArtist发布于 2026/3/21更新于 2026/6/1125 浏览
链表分割:以给定值 x 为基准划分链表

链表分割算法详解

问题描述

给定一个链表的头指针 pHead,以及一个整数值 x。要求将链表分割成两部分,使得所有小于 x 的节点排在大于或等于 x 的节点之前。分割后需保持原数据的相对顺序不变,并返回新链表的头指针。

约束条件:

  • 时间复杂度:O(n)
  • 空间复杂度:O(1)
  • 不能改变原有节点的相对顺序

思路分析

要实现原地分割且保持顺序,直接修改节点指针是最优解。核心思路是利用两个哨兵节点(Dummy Node)分别构建两条临时链表:一条存放小于 x 的节点,另一条存放大于等于 x 的节点。

具体步骤如下:

  1. 初始化哨兵位:创建 guardLess 和 guardGreater 两个虚拟头结点,避免处理空指针边界情况。
  2. 维护尾指针:分别记录两条临时链表的尾部 lessTail 和 greaterTail,这样在插入新节点时可以直接通过尾插法完成,无需遍历查找末尾。
  3. 遍历原链表:使用移动指针 curNode 扫描原链表。根据节点值与 x 的比较结果,将其尾插到对应的临时链表中。
  4. 连接链表:遍历结束后,将 lessTail 指向 guardGreater 的下一个节点,实现两段链表的拼接。
  5. 收尾工作:务必将新链表的最后一个节点 next 置为 nullptr,防止形成环;最后释放哨兵节点占用的内存。

注意:实际编写时,记得断开 greaterTail->next,否则如果原链表后续还有数据,可能会造成逻辑混乱或死循环。

代码实现

以下是基于 C++ 的标准实现,注重指针操作的准确性与内存安全。

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;

         (curNode) {
             (curNode->val < x) {
                
                lessTail->next = curNode;
                lessTail = lessTail->next;
            }  {
                
                greaterTail->next = curNode;
                greaterTail = greaterTail->next;
            }
            
            curNode = curNode->next;
        }

        
        lessTail->next = guardGreater->next;

        
        greaterTail->next = ;

        
        ListNode* result = guardLess->next;

        
         guardLess;
         guardGreater;

         result;
    }
};
// 分别创建两个链表的尾结点,方便尾插时无需频繁找尾
// curNode 为移动指针,用于遍历原链表
while
if
// 小于 x 的结点尾插到 guardLess 链表中
else
// 大于等于 x 的结点尾插到 guardGreater 链表中
// 每次循环中 curNode 指针向后移动
// 链接两个新链表
// 最后一个结点的 next 指针需要置空,防止链表带环
nullptr
// 保存新链表的头结点
// 释放手动开辟的哨兵位头结点
delete
delete
return

优化说明

上述方案已经实现了 O(n) 的时间复杂度和 O(1) 的空间复杂度,逻辑清晰且效率最优,通常无需进一步重构。在实际工程中,重点应放在边界条件的处理上,例如空链表、单节点链表以及所有节点都满足或不满足条件的情况,上述代码已覆盖这些场景。


该算法是链表操作中的经典案例,掌握哨兵节点的使用技巧能极大简化指针操作逻辑。

目录

  1. 链表分割算法详解
  2. 问题描述
  3. 思路分析
  4. 代码实现
  5. 优化说明
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • GLM-CookBook:智谱 GLM 大模型 API 入门指南
  • 打造 AI 产品经理:关键技能与入门指导
  • VS Code 中 GitHub Copilot 与 Git 集成配置指南
  • Python 爬虫开发指南:从 Requests 到 Scrapy 分布式实战
  • SpringBoot 集成 Spring AI 实现简易智能助手
  • Python 量化实战:AKshare 零成本获取全市场金融数据
  • VSCode + Copilot 接入 DeepSeek 模型配置指南
  • 黑马商城 ElasticSearch 搜索功能实战
  • 前后端分离架构 vs 传统架构:核心差异与选型指南
  • 基于开源模型的成人内容过滤合规解决方案
  • Rust 异步缓存系统的设计与实现
  • Google 防御史上最大 DDoS 攻击:峰值 3.98 亿 rps
  • Python 开发环境安全:为何不应在下载目录直接运行脚本
  • .NET Core 自定义 dotnet new 微服务模板实战
  • 万方 AIGC 检测未通过?多款降重工具实测对比
  • C 语言文件加密实现与安全编程实践
  • 利用 AI 生成融合四库文化与地域特色的网名
  • VSCode 使用 Git 快速提交代码指南
  • Flutter wasm_interop 在鸿蒙 Web 端的适配与性能优化指南
  • 三数之和算法详解:排序与双指针

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如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