跳到主要内容
极客日志极客日志
首页博客AI提示词GitHub精选代理工具
搜索
|注册
博客列表
C算法

链表面试基础:快慢指针与哨兵节点的实战应用

链表是数据结构面试中的高频考点。针对中间结点查找与有序链表合并问题,分别采用快慢指针与哨兵节点策略优化解法。前者避免二次遍历,后者简化边界判断。代码基于 C 语言实现,注重内存管理与逻辑清晰性,适合初学者夯实基础并应对面试场景。

FrontendX发布于 2026/3/15更新于 2026/4/263 浏览
链表面试基础:快慢指针与哨兵节点的实战应用

链表是数据结构面试中的高频考点。掌握核心技巧往往比死记硬背代码更重要,本文通过两个经典题目解析关键思路。

876. 链表的中间结点

寻找中间结点看似简单,但边界情况容易出错。常规思路是先遍历一次统计长度,算出 mid 后再移动指针。这种方法需要两次扫描,效率略低。

更优雅的做法是使用快慢指针。让慢指针每次走一步,快指针每次走两步。当快指针到达尾部时,慢指针自然指向中间位置。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
typedef struct ListNode ListNode;
struct ListNode* middleNode(struct ListNode* head) {
    // 创建快慢指针,初始都指向头节点
    ListNode* fast = head;
    ListNode* slow = head;
    
    // 循环条件需同时满足:fast 不为空且 fast->next 不为空
    // 这样能兼容奇数和偶数长度的链表
    while(fast != NULL && fast->next != NULL) {
        slow = slow->next;       // 慢指针移动一节点
        fast = fast->next->next; // 快指针移动两节点
    }
    return slow;
}

为什么这么写? 找中点时,关注的是慢指针的位置。快指针速度是慢指针的两倍,当它走到尾或空时,慢指针刚好走了半程。循环条件用'且'而非'或',是因为只有当 fast 和 next 都存在时,才能安全执行 fast->next->next,避免空指针解引用。

21. 合并两个有序链表

合并两个有序链表时,直接比较大小并尾插新节点是直观做法,但需要处理大量空指针判断,代码冗余较多。

引入'哨兵节点'可以简化逻辑。哨兵节点是一个不存储有效数据的临时头节点,它的 next 指针最终指向真正的头节点。使用哨兵后,无需在循环内判断是否为第一次插入,统一进行尾插操作即可。

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
    // 处理空链表边界
    if(list1 == NULL) return list2;
    if(list2 == NULL) return list1;
    
    // 申请哨兵节点空间
    ListNode* newhead = (ListNode*)malloc(sizeof(ListNode));
    ListNode* newtail = newhead;
    
    ListNode* l1 = list1;
    ListNode* l2 = list2;
    
    // 双指针遍历比较
    while(l1 != NULL && l2 != NULL) {
        if(l1->val < l2->val) {
            newtail->next = l1;
            newtail = newtail->next;
            l1 = l1->next;
        } else {
            newtail->next = l2;
            newtail = newtail->next;
            l2 = l2->next;
        }
    }
    
    // 将剩余非空链表直接接在尾部
    if(l1) newtail->next = l1;
    if(l2) newtail->next = l2;
    
    // 保存结果头节点并释放哨兵
    ListNode* retnewhead = newhead->next;
    free(newhead);
    return retnewhead;
}

关键点说明:

  1. 哨兵的作用:消除了对 newhead 是否为空的判断,统一了插入逻辑。
  2. 内存管理:哨兵节点是动态申请的,最后必须释放,防止内存泄漏。
  3. 返回值:返回的是 newhead->next,因为哨兵本身不是数据节点。

掌握这两个技巧,不仅能解决当前问题,也为后续攻克双向链表、复杂指针操作打下坚实基础。刷题重在理解背后的设计思想,积跬步以致千里。

目录

  1. 876. 链表的中间结点
  2. 21. 合并两个有序链表
  • 💰 8折买阿里云服务器限时8折了解详情
  • 💰 8折买阿里云服务器限时8折购买
  • 🦞 5分钟部署阿里云小龙虾了解详情
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

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

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

更多推荐文章

查看全部
  • RTD1296PB 与 RK3568:NAS 及智能家居芯片实战性能对比
  • 相干伊辛机在医疗与医疗 AI 领域的应用前景
  • 人工智能:循环神经网络(RNN)与序列数据处理实战
  • AI 创作者的多维价值与深远影响
  • OpenClaw Java:基于 Spring Boot 的 AI Agent Gateway 全栈实现
  • 算法实战:归并排序与数组逆序对详解
  • 二叉树深度优先遍历实战:计算布尔值与路径数字和
  • TarsGo 多语言生态:如何与 Java、C++、PHP 等服务互通
  • 电科金仓异构多活架构助力浙江省人民医院信创改造
  • 西门子 S7-1200 PLC 与爱普生机器人 Modbus TCP 通讯配置
  • ASR 自动语音识别原理与 Whisper 模型解析
  • 本地部署 Stable Diffusion 3.5 使用 ComfyUI 图文教程
  • 如何卸载 WSL2 中安装的 Ubuntu 22.04
  • 从零到一:Ubuntu上llama.cpp的编译艺术与性能调优实战
  • Java Employee 类实现与基础控制结构解析
  • C++ 异常处理机制详解
  • C++ STL 常用容器用法总结
  • VSCode Copilot 登录异常排查与修复指南
  • C++ 核心面试题解析(一)
  • Claude Code AI 编程工具项目实战详解

相关免费在线工具

  • 加密/解密文本

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