从被追问到被点赞:我靠“哨兵+快慢指针”展示了面试官真正想看的代码思维

面试高频链表题精讲:从哨兵节点到快慢指针

在算法面试中,链表 是一类非常经典的数据结构题型。它不像数组那样支持随机访问,但正因如此,很多操作都需要我们对指针(引用)有精准的控制。本文将通过四道典型题目,带你系统掌握链表处理中的两大核心技巧:哨兵节点(Dummy Node)快慢指针(Fast & Slow Pointers)


一、删除链表中的指定节点:为什么需要哨兵节点?

题目描述

给定一个单链表的头节点 head 和一个值 val,删除链表中所有值等于 val 的节点,并返回新的头节点。

力扣:LCR 136. 删除链表的节点 - 力扣(LeetCode)

初步解法(不使用哨兵)

js 复制代码
function remove(head, val) {
  // 特殊处理头节点
  if (head && head.val === val) {
    return head.next;
  }
  let cur = head;
  while (cur.next) {
    if (cur.next.val === val) {
      cur.next = cur.next.next;
      break; // 假设只删第一个匹配项
    }
    cur = cur.next;
  }
  return head;
}

面试官反问:

"你为什么要单独判断头节点?能不能统一处理?"

这是一个非常关键的问题!因为头节点没有前驱节点,所以当我们想"让前一个节点跳过当前节点"时,头节点就成了特例。

引入哨兵节点(Dummy Node)

哨兵节点是一个人为添加的假节点 ,通常放在链表头部,其作用是消除边界条件的特殊处理

js 复制代码
function remove(head, val) {
  const dummy = new ListNode(0);
  dummy.next = head;
  let cur = dummy;
  while (cur.next) {
    if (cur.next.val === val) {
      cur.next = cur.next.next;
      break;
    }
    cur = cur.next;
  }
  return dummy.next; // 返回真正的头节点
}

优势

  • 不再需要单独判断头节点是否为待删节点;
  • 所有节点都变成了"中间节点",逻辑统一;
  • 即使链表为空或全被删完,也能安全返回。

二、反转链表:哨兵 + 头插法

题目描述

反转一个单链表。

力扣:206. 反转链表 - 力扣(LeetCode)

解法思路

我们可以利用哨兵节点作为新链表的头 ,然后遍历原链表,每次把当前节点插入到哨兵之后 ------这就是头插法

js 复制代码
function reverseList(head) {
  const dummy = new ListNode(0); // 哨兵,dummy.next 指向已反转部分的头
  let cur = head;
  while (cur) {
    const next = cur.next;       // 1. 保存下一个节点
    cur.next = dummy.next;       // 2. 当前节点指向已反转部分的头
    dummy.next = cur;            // 3. 更新反转部分的新头
    cur = next;                  // 移动到原链表下一节点
  }
  return dummy.next;
}

🔍 关键理解

  • dummy 始终不动,它的 next 指向当前已反转链表的头
  • 每轮操作把 cur 插到最前面,实现"头插";
  • 三步操作顺序不能乱,否则会断链。

💡 虽然这道题也可以用递归或双指针(prev/cur)实现,但哨兵+头插法提供了一种清晰、不易出错的迭代思路。


三、判断链表是否有环:从哈希表到快慢指针

题目描述

给定一个链表,判断其中是否存在环。

力扣:141. 环形链表 - 力扣(LeetCode)

解法一:哈希表(空间换时间)

js 复制代码
let hash = new Map();
let temp =head;
while(temp)
 {
   if(hash.has(temp))
    return true;
   else
    hash.set(temp,1);
  temp=temp.next;
 }
  • 时间复杂度:O(n)
  • 空间复杂度:O(n)

面试官追问:

"能不能不用额外空间?"

解法二:快慢指针(Floyd 判圈算法)

核心思想:如果链表有环,快指针(每次走两步)一定会在环内追上慢指针(每次走一步)。

js 复制代码
function hasCycle(head) {
  let slow = head;
  let fast = head;
  while (fast && fast.next) {
    slow = slow.next;         // 慢指针走1步
    fast = fast.next.next;    // 快指针走2步
    if (slow === fast) {      // 比较引用地址(同一内存)
      return true;
    }
  }
  return false;
}

优势

  • 空间复杂度 O(1);
  • 时间复杂度 O(n);
  • 是链表环检测的标准解法。

🌟 快慢指针不仅用于判环,还可用于找环入口、求中点、删除倒数第 N 个节点等。


四、删除链表的倒数第 N 个节点:哨兵 + 快慢指针的完美结合

题目描述

给你一个链表,删除倒数第 n 个节点,并返回链表头。

力扣:19. 删除链表的倒数第 N 个结点 - 力扣(LeetCode)

解法思路

  1. 使用哨兵节点避免头节点被删的边界问题;
  2. 快指针先走 n 步
  3. 然后快慢指针同步移动 ,当快指针到达末尾时,慢指针正好在倒数第 n 个节点的前一个
  4. 执行删除操作。
js 复制代码
const removeNthFromEnd = function(head, n) {
  const dummy = new ListNode(0);
  dummy.next = head;
  let fast = dummy;
  let slow = dummy;

  // 快指针先走 n 步
  for (let i = 0; i < n; i++) {
    fast = fast.next;
  }

  // 快慢指针一起走,直到 fast 到达最后一个节点
  while (fast.next) {
    fast = fast.next;
    slow = slow.next;
  }

  // 此时 slow 指向倒数第 n 个节点的前一个
  slow.next = slow.next.next;

  return dummy.next;
};

🎯 为什么需要哨兵?

  • 如果要删除的是头节点 (比如链表长度为 5,n=5),那么 slow 需要停在"头节点之前";
  • 没有哨兵的话,slow 无法指向 null 的前驱;
  • 哨兵确保 slow 始终有效,且 slow.next 可安全删除。

总结:链表面试两大法宝

技巧 适用场景 核心价值
哨兵节点(Dummy) 删除、插入、反转等涉及头节点的操作 消除边界条件,统一逻辑
快慢指针 判环、找中点、倒数第 N 个节点 O(1) 空间解决距离/位置问题

在实际面试中,先写出朴素解法(如哈希表) ,再根据面试官提示优化到快慢指针 ,能体现你的思维层次;而哨兵节点则是写出健壮、简洁代码的关键技巧。


希望这篇文章能帮你打通链表题的任督二脉!下次遇到链表题,先问自己两个问题:

  1. 要不要加哨兵? → 避免头节点特殊处理
  2. 能不能用快慢指针? → 解决"倒数"、"中点"、"环"等问题

祝你面试顺利,Offer 收割!🎉

相关推荐
可信计算3 小时前
【算法随想】一种基于“视觉表征图”拓扑变化的NLP序列预测新范式
人工智能·笔记·python·算法·自然语言处理
树下水月3 小时前
纯HTML 调用摄像头 获取拍照后的图片的base64
前端·javascript·html
蜗牛攻城狮3 小时前
Vue 中 `scoped` 样式的实现原理详解
前端·javascript·vue.js
月明长歌3 小时前
【码道初阶】【LeetCode 110】平衡二叉树:如何用一个“Magic Number”将复杂度从O(N²)降为 O(N)?
linux·算法·leetcode
yaoh.wang3 小时前
力扣(LeetCode) 14: 最长公共前缀 - 解法思路
python·程序人生·算法·leetcode·面试·职场和发展·跳槽
豆苗学前端3 小时前
前端工程化终极指南(Webpack + Gulp + Vite + 实战项目)
前端·javascript
比老马还六3 小时前
Bipes项目二次开发/海龟编程(六)
前端·javascript
瘦的可以下饭了3 小时前
2 数组 递归 复杂度 字符串
前端·javascript
历程里程碑3 小时前
C++ 9 stack_queue:数据结构的核心奥秘
java·开发语言·数据结构·c++·windows·笔记·算法