链表去重问题:快慢指针法遇空指针异常及返回头节点困惑
解决链表去重的空指针异常与头节点丢失问题
看起来你的快慢指针逻辑有点走偏啦,咱们一步步捋清楚问题出在哪,再修正代码:
你的代码存在的核心问题
- 丢失原始头节点:你最后返回的
current在遍历过程中一直往后移动,循环结束后它指向的是链表的末尾(甚至null),自然没法返回修改后的完整链表头。 - 快慢指针逻辑错误:你把runner和current同步移动了,这不是快慢指针去重的正确用法——慢指针应该停在当前不重复的节点,快指针负责跳过所有重复的节点。
- 空指针风险:当
current.next已经是null的时候,你还去访问current.next.next,这必然会抛出空指针异常。 - 循环条件冗余且混乱:同时判断
current、runner、runner.next会导致逻辑混乱,而且runner是从current衍生出来的,不需要单独提前判断。
修正后的代码实现
Node RemoveDuplicates(Node head) { // 空链表直接返回 if (head == null) { return null; } // 保存原始头节点,最后要返回它 Node current = head; // 当current还有下一个节点时继续处理 while (current != null && current.next != null) { // runner从current的下一个节点开始遍历 Node runner = current.next; // 跳过所有和current.data相同的节点 while (runner != null && runner.data == current.data) { runner = runner.next; } // 把current的next指向第一个不重复的节点 current.next = runner; // current移动到下一个不重复的节点 current = runner; } // 原始头节点一直没被修改,直接返回 return head; }
代码解释
- 保留头节点:一开始就用
current指向头节点,但最后返回的是原始的head,因为头节点本身不会被移除(除非整个链表为空,已经提前处理)。 - 正确的快慢指针逻辑:
- 慢指针
current:停在当前已经确认不重复的节点。 - 快指针
runner:从current.next出发,跳过所有和current.data相同的节点,直到找到第一个不同的节点或者链表末尾。
- 慢指针
- 避免空指针:每次访问
runner之前都先判断runner != null,修改current.next时也确保不会访问null的下一级。 - 清晰的循环条件:外层循环只需要判断
current和current.next不为null,确保我们有节点可以处理。
这样修改后,既能正确移除所有重复节点,也不会出现空指针异常,最后返回的是修改后的完整链表头节点。
内容的提问来源于stack exchange,提问作者Bo Jackson
相关产品推荐
相关产品推荐

