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

LeetCode两数相加实现中ListNode迭代ans=ans.next时节点被覆盖问题

问题描述

无法迭代到下一个ListNode节点,原因是当前节点被listnode.next的值覆盖。
这是一道两数相加的算法题,参考题解后按自身逻辑编写实现代码时,无法正常迭代到下一个链表节点。
问题代码如下:

public ListNode AddTwoNumbers(ListNode l1, ListNode l2)
{
    try
    {
        string l1NodeData = null;
        string l2NodeData = null;

        do
        {
            l1NodeData = l1NodeData + l1.val;
            l1 = l1.next;
        } while (l1 != null);

        do
        {
            l2NodeData = l2NodeData + l2.val;
            l2 = l2.next;
        } while (l2 != null);

        int sum = Convert.ToInt32(l1NodeData) + Convert.ToInt32(l2NodeData);

        var sumInChar = sum.ToString().ToArray();

        ListNode dummyhead = new ListNode(0);
        ListNode ans = dummyhead;

        for (int i = sumInChar.Length - 1; i > 0; i--)
        {
            ans.val = Convert.ToInt32(sumInChar[i].ToString());
            ListNode tempListNode = new ListNode(Convert.ToInt32(sumInChar[i - 1].ToString()));
            ans.next = tempListNode;
            ans = ans.next;

            //此处执行ans = ans.next赋值下一个节点后,当前节点的数据会被覆盖
        }

        return ans;
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex);
        throw;
    }
}

上述代码中,在执行ans = ans.next赋值操作时,当前节点会被下一个节点的值覆盖,预期仅为移动指针到下一个节点以完成迭代遍历,需要排查问题原因并给出可行解决方案。

问题根因

你觉得节点被覆盖是完全的误解,ans = ans.next本身就是游标移动的标准写法,不会覆盖之前已经挂载到链表上的节点,代码出问题的核心原因有三个:

  • 返回值错误:你初始化的dummyhead才是整条结果链表的起点,ans只是用来移动的临时游标,循环结束后ans已经指向链表的最后一个节点,你直接返回ans相当于只返回了链表的尾巴,前面拼接的所有节点都没有被返回,看起来就像节点被覆盖了。
  • 循环边界错误:构造结果链表的for循环条件写的是i > 0,会漏掉求和结果最高位的处理,而且循环里先给当前游标节点赋值、再创建下一个节点的顺序完全写反了。
  • 数值溢出风险:把链表值转成字符串再转int求和的逻辑,只要链表长度超过10位就会超出int取值范围直接抛异常,完全不符合长链表的测试场景。
修复方案

先修复链表迭代逻辑(保留原思路,仅修正链表操作问题)

注意这个版本仍然存在数值溢出问题,仅用来演示虚拟头节点+游标遍历链表的正确写法:

public ListNode AddTwoNumbers(ListNode l1, ListNode l2)
{
    string l1NodeData = null;
    string l2NodeData = null;

    do
    {
        l1NodeData = l1NodeData + l1.val;
        l1 = l1.next;
    } while (l1 != null);

    do
    {
        l2NodeData = l2NodeData + l2.val;
        l2 = l2.next;
    } while (l2 != null);
    // 即使换成long,也无法支持几十上百位的超长链表
    long sum = Convert.ToInt64(l1NodeData) + Convert.ToInt64(l2NodeData);
    var sumInChar = sum.ToString().ToArray();

    ListNode dummyhead = new ListNode(0);
    // ans作为移动游标,初始指向虚拟头节点
    ListNode ans = dummyhead;

    // 从最低位(数组末尾)遍历到最高位(数组0下标)
    for (int i = sumInChar.Length - 1; i >= 0; i--)
    {
        // 为当前位创建新节点,挂载到游标所在节点的next位置
        ListNode tempListNode = new ListNode(Convert.ToInt32(sumInChar[i].ToString()));
        ans.next = tempListNode;
        // 游标移动到新创建的节点,之前的节点已经被dummyhead串成完整链表,不会丢失
        ans = ans.next;
    }
    // 虚拟头节点本身是占位用的0值,真正的结果链表从next位置开始
    return dummyhead.next;
}

正确标准解法(逐位相加处理进位,无溢出问题)

这道题的标准实现不需要做字符串、整数的类型转换,直接同步遍历两个输入链表,逐位计算和与进位即可,适配任意长度的链表:

public ListNode AddTwoNumbers(ListNode l1, ListNode l2)
{
    ListNode dummyHead = new ListNode(0);
    ListNode curr = dummyHead;
    int carry = 0; // 存储进位值
    // 只要两个链表有一个没遍历完,或者还有剩余进位,就继续生成节点
    while (l1 != null || l2 != null || carry != 0)
    {
        int x = l1 != null ? l1.val : 0;
        int y = l2 != null ? l2.val : 0;
        int bitSum = x + y + carry;
        carry = bitSum / 10;
        // 当前位的值是bitSum对10取余
        curr.next = new ListNode(bitSum % 10);
        curr = curr.next;
        if (l1 != null) l1 = l1.next;
        if (l2 != null) l2 = l2.next;
    }
    return dummyHead.next;
}

写链表操作的代码时记住一个原则:用虚拟头节点锚定链表起点,用单独的游标变量做移动遍历,最后永远返回虚拟头节点的next,就不会出现丢节点、返回错位置的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 05:06:05