【发布时间】:2015-05-04 05:18:16
【问题描述】:
这是关于https://oj.leetcode.com/problems/add-two-numbers/的问题
给定两个链表,表示两个非负数。 数字以相反的顺序存储,它们的每个节点都包含 一个数字。将两个数字相加并作为链表返回。
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
我遵循的逻辑是我假设 list1 比 list2 长,否则交换它们。然后,我通过在 list2 的末尾添加包含零的节点来使 list2 的长度等于 list1。 (此时代码会打印两个列表以检查是否存在错误)。在此之后,我从头开始遍历列表,添加单个数字,用数字总和模 10 覆盖链表 1 中的值。还记录了进位值。这样做直到列表结束。如果最后进位值不为零,则创建一个包含进位值的新节点,并将其插入到链表1的末尾。返回链表1的头。
代码在所有情况下都能正常工作,除了必须在最后添加一个带有进位值的新节点的情况。我在返回值之前打印链表 1,此时它是正确的。但是,返回头部并在主函数中打印它会给出错误的答案,节点中应该包含进位数字的垃圾值。这几乎就像带有进位数字的节点被2-3个带有垃圾值的节点所取代。有人可以解释一下吗?
我观察到的另一个问题是在打印最终答案时,如果我使用cout << ans->val << " " << endl,代码会正确终止(返回 0)但会打印不正确的输出。如果我删除 endl ,即使用 cout << ans->val << " " ,则代码会通过引发运行时错误(段错误)终止。我想不出一个合适的理由。
感谢您的时间和帮助。
#include <iostream>
using namespace std;
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
class Solution {
public:
ListNode *addTwoNumbers(ListNode *l1, ListNode *l2)
{
ListNode* l1_mover = l1;
ListNode* l2_mover = l2;
while ((l1_mover->next != NULL) && (l2_mover->next != NULL))
{
l1_mover = l1_mover->next;
l2_mover = l2_mover->next;
}
if ((l1_mover->next == NULL) && (l2_mover->next != NULL))
{
// Call the function after swapping the lists if the first one is smaller
cout << "calling function with swapped lists " << endl;
return addTwoNumbers(l2, l1);
}
while (l1_mover->next != NULL)
{
ListNode emp(0);
l2_mover->next = &emp;
l1_mover = l1_mover->next;
}
// Till now, I have equated the lengths of both the lists, by padding the shorter one with zeros.
cout << "printing list 1 inside. " << endl;
l1_mover = l1;
while (l1_mover != NULL)
{
cout << l1_mover->val << " ";
l1_mover = l1_mover->next;
}
cout << endl;
cout << "printing list 2 inside. " << endl;
l2_mover = l2;
while (l2_mover != NULL)
{
cout << l2_mover->val << " ";
l2_mover = l2_mover->next;
}
cout << endl;
// The above two print statements show that the lists are still correct
l1_mover = l1;
l2_mover = l2;
int carry = 0;
while (l1_mover != NULL)
{
int digit_sum = l1_mover->val + l2_mover->val + carry;
carry = digit_sum / 10;
l1_mover->val = digit_sum % 10;
//cout << "sum is " << digit_sum << " and l2 val is " << l2_mover->val << endl;
if (l1_mover->next == NULL)
break;
// the above break is so that l1 is not NULL at end of loop.
l1_mover = l1_mover->next;
l2_mover = l2_mover->next;
}
if (carry != 0)
{
cout << "carry not zero " << carry << endl;
ListNode last_one(carry);
l1_mover->next = &(last_one);
}
cout << endl << "printing ans inside. " << endl;
l1_mover = l1;
while (l1_mover != NULL)
{
cout << l1_mover->val << " ";
l1_mover = l1_mover->next;
}
cout << endl << endl;
// The above lines print the linked list containing the sum. It is observed to be correct.
return l1;
}
};
int main()
{
ListNode a1(8);
ListNode b1(7);
ListNode b2(9);
b1.next = &b2;
Solution object;
ListNode* ans = object.addTwoNumbers(&a1, &b1);
cout << "printing ans " << endl;
while (ans != NULL)
{
cout << ans->val << " " << endl;
// cout << ans->val << " "; // if this line is used, instead of the above one,
// the program terminates with an error message. It doesn't give an error if the other line
// is used.
ans = ans->next;
}
}
【问题讨论】:
-
复制粘贴编译你的代码和代码段错误,你也明白了吗?
-
在终端打印很多东西后是否出现了段错误?包括句子“printing ans”。我在问题的第二部分提到了这一点。我只在第二种情况下遇到段错误。但是,这可能是我的机器特有的。因此,为了回答您的查询,在打印很多内容(包括“打印 ans”)后会出现段错误。在此之前,它不是。
-
您正在存储指向在您访问它们时生命周期已结束的对象的指针(
&emp,&last_one)。您需要动态分配。 -
为什么要先补零?这似乎是一个不必要的步骤 - 遍历列表求和;当您点击
NULL时停止更新该指针,并添加0。 -
@molbdnilo:谢谢。我知道问题与范围和内存分配有关。只是我认为以我的方式调用构造函数与动态分配相同。回想起来,这似乎是一个愚蠢的想法。修复了代码。