You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

链表去重代码疑问:为何函数结束时head为null仍正确?

问题解析:为何removeDuplicates函数中head最终为null但仍能正确去重?

先贴出你提供的代码:

static void removeDuplicates(Node head) {
    HashSet<Integer> set = new HashSet<>();
    Node previous = null;

    while (head != null) {
        if (set.contains(head.data)) {
            previous.next = head.next;
        } else {
            set.add(head.data);
            previous = head;
        }
        head = head.next;
    }
}

核心原因:Java的参数传递是值传递

你混淆了函数内的「局部变量head」和调用者传入的「链表头引用」。函数里的head只是传入引用的一个副本——你在函数里执行head = head.next,只是改变了这个局部副本的指向,完全不会影响调用者那边原本的链表头变量。

函数真正的作用:修改链表的结构(而非头引用)

这个函数的核心逻辑是通过修改节点的next指针来跳过重复节点:

  • 当检测到重复节点时,让previous.next指向当前节点的下一个节点,相当于把当前重复节点从链表中移除
  • 遇到非重复节点时,将当前节点数据加入集合,并把previous移动到当前节点,继续遍历

整个过程中,链表的实际结构(节点间的连接关系)被修改了,而局部变量head只是用来遍历链表的工具,它最后变成null只是遍历到链表末尾的标志,和链表本身的正确性毫无关系。

举个直观例子:
假设原链表是1 -> 2 -> 2 -> 3

  1. 初始head指向1,将1加入集合,previous变为1,head移动到2
  2. 第二个2被检测到重复,previous.next(也就是1的next)指向3,跳过第二个重复节点
  3. head继续移动到3,将3加入集合,previous变为3,head移动到null,循环结束

最终链表变成1 -> 2 -> 3,完全符合去重预期,而函数里的head只是遍历到了末尾的null,根本不会影响调用者手里的原链表头引用。

额外补充:函数的小缺陷

这个函数存在一个边界问题:如果链表的第一个节点就是重复的(比如1 -> 1 -> 2),它没法修改头节点——因为previous初始为null,第一次遇到重复时执行previous.next会抛出空指针异常。不过这和你问的head变null的问题无关,只是顺便提一下。

内容的提问来源于stack exchange,提问作者oerol

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 07:01:06