面试:对两个链表中的数字求和
在昨天的一次采访中,有人问我如何对两个包含数字的单链表的值求和。他们还表示,这些列表的长度可能不等。
我问列表是否是向后存储的,因为这就是我在大学了解到的,但他们说不是,它是向前存储的。他们还说我不能简单地反转列表,然后添加,然后反转它以再次向前移动,因为该选项需要太多处理。我在网上能找到的都是这种解决方案。
即使他们暗示我应该使用递归函数来完成此操作,我也无法给出答案。
谁能帮我解决这个问题。这是一份 C++ 工作,我希望如果我接到回电并且我能够解释我研究了该解决方案,他们可能会认为这是一个好兆头。谢谢。
对于那些对求和应该如何工作感到困惑的人,它以这种方式呈现。
列表1:1->2->9 列表 2:1->3
因此,由于数字是向前存储的,因此我需要首先添加 9 和 3(两个列表的末尾)。然后取 1 进位并执行 1 + 2 + 1。等等。
During an interview yesterday, I was asked how I would go about summing the values of two singly linked lists that contained digits. They also said the lists could be unequal lengths.
I asked if the list was stored backwards, as that's how I learned about it at uni, but they said no, it was stored forward. They also said I couldn't simply reverse the lists, add then, then reverse it to get it forward again because that option required too much processing. This sort of solution is all I've been able to find online.
I was unable to give an answer, even after they hinted that I should be doing this with a recursive function.
Can anyone help me out with what the solution would have been. This was for a C++ job and I'm hoping that if I ever get called back and I'm able to explain I researched the solution, they might see that as a good sign. Thank you.
For those confused about how the summation is supposed to work, it was presented in this way.
List 1: 1->2->9
List 2: 1->3
So since the numbers are stored forward, I would need to begin by adding the 9 and 3 (end of both lists). Then take the 1 carry and do 1 + 2 + 1. Etc.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您计算两个列表的长度。您在较短的列表的开头填充一些 0 数字,以便它们的长度相等。现在你用额外的 0 填充两个数字(它将被第一个数字的进位使用。因此 9 + 1 = 10 是可能的)。
您创建第三个链表,其长度等于前两个链表。
现在你创建一个像这样的类:
和一个像这样的函数:
runningTotal
链接列表。您只向第一级 Sum 提供运行总计的“头”。还有另一种可能性,更复杂,但不需要预先计算列表的长度。它使用两个递归函数:
第一个递归函数只是在左右都存在时简单地遍历左右两个函数。如果两者同时完成,那么您可以像前面的示例一样简单地回滚。
如果其中一个先于另一个完成,那么您可以使用另一个递归函数,如下所示(*extraDigits 的初始值为 1):
当该函数最终返回时,我们有一个暂存器,从中提取数字和暂存器的长度
我们的第一个递归函数的最内层现在必须将最短链表的当前数字与暂存器的最后一位数字相加,并将最长链表的当前数字放入暂存器中代替刚刚使用的数字。现在,您展开递归函数,并将暂存器用作循环数组。完成展开后,您可以将元素直接从暂存器添加到 runningTotal 链接列表中。
正如我所说,它有点复杂,但在 1-2 小时内我可以把它写成一个程序。
示例(不带进位)
递归前两个元素的 。现在您
看到第二个列表已完成并且您使用了第二个函数。
现在我们回到之前的函数
You count the length of both lists. You pad at the beginning the shorter list with a number of 0 digits so that they are equal in length. Now you pad both numbers with an extra 0 (it will be used by the carry of the first digits. So that it's possible that 9 + 1 = 10).
You create a third linked list of length equal to the previous two.
Now you do a class like this:
and a function like this:
runningTotal
linked list directly in Sum. You give to the first level Sum only the "Head" of the Running Total.There is another possibility, much more complex, but that doesn't require to pre-count the length of the lists. It uses two recursive functions:
The first recursive function simply traverses left and right while both are present. If both finishes at the same time then you can simply roll-back as in the previous example.
If one of them finishes before the other, then you use another recursive function like this (the initial value of *extraDigits is 1):
when this function finally returns, we have a scratchpad from where to extract the digits and the length of the scratchpad
The innermost level of our first recursive function has now to sum its current digit of the shortest linked list with the last digit of the scratchpad and put the current digit of the longest linked list in the scratchpad in place of the digit just used. Now you unroll your recursive function and you use the scratchpad as a circular array. When you finish unrolling, then you add elements to the runningTotal linked list taking them directly from the scratchpad.
As I've said, it's a little complex, but in 1-2 hours I could write it down as a program.
An example (without carry)
you recurse the first two elements. So you have
Now you see that the second list is finished and you use the second function.
Now we return to the previous function
我将以这样的方式解决这个问题
让我们假设这两个列表是:
1->2->7->6->4->3 和
5->7->2
总和为
1->2->7 + Sum(6->4->3, 5->7->2)
现在我们创建一个函数,它接受 2 个相同大小的列表并返回它们的总和
类似
,这与基本情况
if(list1->next == NULL) return list1->val+list2->val;
注意::我们可以轻松处理下一次传递中的进位,或者您可以在我们的 sum 函数本身中处理它
所以毕竟我们的 ans 将是
1 ->2->7->11->11->5
然后递归执行 %10 并取进位并将其添加到先前的值。
所以最终的 ans 将是
1->2->8->2->1->5
I will approach this problem in something like this
Let's suppose the 2 lists are :
1->2->7->6->4->3 and
5->7->2
The sum is
1->2->7 + Sum(6->4->3, 5->7->2)
Now we make a function that take 2 lists of same size and returns their sum
which will be something like
with base case
if(list1->next == NULL) return list1->val+list2->val;
Note :: we can handle the carry in next pass easily or you can handle that in our sum function itself
So after all this our ans will be
1->2->7->11->11->5
then recursively do %10 and take carry and add it to previous value.
so final ans will be
1->2->8->2->1->5
我会创建一个像 *head 或 *tail 这样的节点来存储我开始的节点的地址,然后迭代列表以确保我不会回到起点。这不需要计算每个的长度,这听起来效率很低。
至于递归性,只需在函数顶部进行此检查并返回 (node->value + myfunct(node->prev));如果您只做一次数学计算,那么效率会更高。
I would have created a node like *head or *tail to store the address of the node that I started from, then iterate through the list making sure im not back at my start point. This doesn't require to to have to count the length of each, which sounds inefficient.
As for the recursiveness just do this check at the top of the function and return (node->value + myfunct(node->prev)); It'd be more efficient given you're doing the math once.
列表“1,2,9”和“1,3”分别代表数字“129”和“13”,在这种情况下总和是“142”。
使用递归
在伪代码中:
作为替代方案,您可以使用堆栈:
The lists "1, 2, 9" and "1, 3" each represent the numbers "129" and "13", in which case the sum is "142".
Using recursion
In pseudocode:
As an alternative, you can use a stack: