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

移除链表倒数第N个节点:双次遍历法空指针错误排查

解决移除链表倒数第N个节点时的空指针错误

你的代码核心问题

  • 循环逻辑完全错误:统计完节点总数count后,你复用count作为第二个循环的终止条件,while(count>0)会让ptr一直走到链表末尾的next(也就是nullptr),后续访问ptr->next必然触发空指针错误。你应该用计算好的remove = count -n -1来控制循环,移动到要删除节点的前一个位置。
  • 未处理删除头节点的边界情况:当要删除的是链表第一个节点(即n == count)时,remove = count -n -1 = -1,不存在“前一个节点”,此时直接返回head->next即可,不能再操作ptr->next。
  • 变量复用导致原数据丢失:统计节点数的count被你在第二个循环中修改,后续无法再获取原节点总数,应该用临时变量做循环计数。

修正后的代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        int count = 0;
        ListNode *ptr = head;

        // 第一次遍历统计节点总数
        while (ptr != nullptr) {
            count++;
            ptr = ptr->next;
        }

        // 处理删除头节点的特殊情况
        if (n == count) {
            ListNode* temp = head;
            head = head->next;
            delete temp; // 可选:释放内存避免泄漏
            return head;
        }

        // 计算需要移动到的位置:倒数第n个节点的前一个
        int steps = count - n - 1;
        ptr = head;

        // 移动到目标位置
        while (steps > 0) {
            ptr = ptr->next;
            steps--;
        }

        // 删除目标节点
        ListNode* temp = ptr->next;
        ptr->next = ptr->next->next;
        delete temp; // 可选:释放内存

        return head;
    }
};

额外优化:单次遍历的快慢指针法

如果想进一步提升效率,可以用快慢指针只遍历一次链表:让快指针先走n步,之后快慢指针同步移动,当快指针走到链表末尾时,慢指针刚好指向倒数第n个节点的前一个位置,无需统计节点总数。示例代码如下:

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        // 用哑节点简化头节点删除的处理逻辑
        ListNode* dummy = new ListNode(0, head);
        ListNode* fast = dummy;
        ListNode* slow = dummy;

        // 快指针先走n+1步
        for (int i = 0; i <= n; i++) {
            fast = fast->next;
        }

        // 快慢指针同步移动,直到快指针到达末尾
        while (fast != nullptr) {
            fast = fast->next;
            slow = slow->next;
        }

        // 删除目标节点
        ListNode* temp = slow->next;
        slow->next = slow->next->next;
        delete temp;

        ListNode* newHead = dummy->next;
        delete dummy;
        return newHead;
    }
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 11:10:42