我最近在接受采访时得到了编程问题。
有2个链接列表。每个节点存储1到9的值(表示数字的一个索引)。因此,123将是链接列表1-> 2-> 3
任务是创建一个函数:
static LinkedListNode getSum(LinkedListNode a, LinkedListNode b)
将返回2个链接列表中的值的总和。
如果阵列a是:1-> 2-> 3-> 4
阵列b为:5-> 6-> 7-> 8
答案应该是:6-> 9-> 1-> 2
这是我的算法:
遍历a和b中的每个节点,将值作为整数获取并添加它们。使用这些值创建新的链接列表。
以下是代码:我假设它的复杂度为O(n)。一次通过每个数组输入,一次创建输出数组。
有什么改进吗?更好的算法......或代码改进
public class LinkedListNode {
LinkedListNode next;
int value;
public LinkedListNode(int value) {
this.value = value;
this.next = null;
}
static int getValue(LinkedListNode node) {
int value = node.value;
while (node.next != null) {
node = node.next;
value = value * 10 + node.value;
}
return value;
}
static LinkedListNode getSum(LinkedListNode a, LinkedListNode b) {
LinkedListNode answer = new LinkedListNode(0);
LinkedListNode ans = answer;
int aval = getValue(a);
int bval = getValue(b);
int result = aval + bval;
while (result > 0) {
int len = (int) Math.pow((double) 10,
(double) String.valueOf(result).length() - 1);
int val = result / len;
ans.next = new LinkedListNode(val);
ans = ans.next;
result = result - val*len;
}
return answer.next;
}
}
答案 0 :(得分:3)
我在这个问题上看到的其他解决方案涉及通过在输入列表上向后迭代来逐步构建返回的列表,同时在转到新列表时添加每个元素。这种方式更复杂,因为你必须添加每个元素并处理结转。
如果阵列a是:1-> 2-> 3-> 4
阵列b为:5-> 6-> 7-> 8
向后迭代
然后4 + 8 = 12(返回列表当前= 2)
携带1
(1)+ 3 + 7 = 11(返回列表= 1-> 2)
携带1
(1)+ 2 + 6 = 9(返回列表= 9 - > 1 - > 2)
1 + 5 = 6(返回列表= 6-> 9> 1-> 2)
如果列表只是单链接,你可以通过使用Stacks来实现这一点,以使LIFO性质向后迭代。
答案 1 :(得分:0)
嗨@rtindru:正如您所说,您要添加两个链接列表。
第一个链接列表a是:1->2->3->4
第二个链接列表b是:5->6->7->8
在问题中没有提到存储在链表中的数字以与出现的数字相同的顺序或相反的顺序存储。第一种方法更难。
第一种方法:
list a: 1234
list b: 5678
答案应该是:6->9->1->2
1 2 3 4
+ 5 6 7 8
-----------------
6 9 1 2
第二种方法
如果数字以相反的顺序存储,那么
第一个链接列表a是:1->2->3->4
。实际号码:N1=4321
。
第二个链表b是:5->6->7->8
。实际号码:N2=8765
。
总和将为6->8->0->3->1
。
这是一种简单的方法。
在你要求第一种方法的问题中,给出的例子也是第一种方法,但你的源代码是第二种方法。请遵守它。
答案 2 :(得分:0)
我看到的其他答案经常依赖额外的堆栈。实际上只有O(1)
额外空间才能解决。我在另一个答案中修改了这个例子,使两个列表的长度不同:
list a is: 1->2->3->4
list b is: 5->6->7->8->3->6
我们可以迭代这两个列表,将当前值的值存储在a
和b
的新列表c
的值中。但我们不能简单地将这两个值的总和作为c
中的值,因为如果两个列表的长度不同,我们无法恢复列表a
中的原始值, b
。
一个小技巧是生成一个两位数的值,第一个数字是a
中的值,第二个数字是b
中的值,如:
list c: 15 <- 26 <- 37 <- 48 <- 3 <- 6
^ pointer "p1"
^ pointer "p2" here to mark the end of list a
完全创建列表c
后,我们从指针&#34; p1&#34;开始倒带。我们首先在指针&#34; p2&#34;中将节点中的两个数字分开,然后将正确的数字添加到p1处的值。然后我们反转p1并设置p1->next
,p2和p2->next
,然后继续前面的节点。
list c: 15 <- 26 <- 37 <- 8 <- 3 -> 4
^ p1
^ p2
carry = 1
时间复杂度为2*max( length(a), length(b) )
。
答案 3 :(得分:0)
这是我对这个问题的回答(使用C#代替Java,但逻辑可以用任何一种语言轻松复制)。我使用链表反转进行正向求和,而对于反向存储,我使用了结转方法。
/* Program: Given two numbers represented in a linked list in reverse order, sum them and store the result in a third linked list
*
* Date: 12/25/2015
*/
using System;
namespace CrackingTheCodingInterview
{
/// <summary>
/// Singly Linked List with a method to add two numbers stored in two linked lists in reverse order
/// </summary>
public partial class SinglyLinkedList
{
/// <summary>
/// Adding two numbers stored in a linked list in reverse order
/// </summary>
/// <param name="num1">Linked List 1 storing number 1</param>
/// <param name="num2">Linked List 2 storing number 2</param>
/// <param name="result">Linked List 3 storing sum of number 1 and number 2</param>
public static void SumNumbersReverse(SinglyLinkedList num1, SinglyLinkedList num2, SinglyLinkedList result)
{
int carryForward = 0;
int sum = 0;
Node num1Digit = num1.head;
Node num2Digit = num2.head;
int sum1 = 0;
int sum2 = 0;
while (num1Digit != null || num2Digit != null)
{
if (num1Digit == null)
{
sum1 = 0;
}
else
{
sum1 = (int)num1Digit.Data;
}
if (num2Digit == null)
{
sum2 = 0;
}
else
{
sum2 = (int)num2Digit.Data;
}
sum = sum1 + sum2 + carryForward;
if (sum > 9)
{
carryForward = 1;
}
else
{
carryForward = 0;
}
result.Insert(sum % 10);
if (num1Digit != null)
{
num1Digit = num1Digit.Next;
}
if (num2Digit != null)
{
num2Digit = num2Digit.Next;
}
}
result.ReverseList();
}
/// <summary>
/// Adding two numbers stored in a linked list in reverse order
/// </summary>
/// <param name="num1">Linked List 1 storing number 1</param>
/// <param name="num2">Linked List 2 storing number 2</param>
/// <param name="result">Linked List 3 storing sum of number 1 and number 2</param>
public static void SumNumbersForward(SinglyLinkedList num1, SinglyLinkedList num2, SinglyLinkedList result)
{
num1.ReverseList();
num2.ReverseList();
SumNumbersReverse(num1, num2, result);
result.ReverseList();
}
/// <summary>
/// Reverse a singly linked list
/// </summary>
public void ReverseList()
{
Node prev = null;
Node curr = head;
Node currNext;
while(curr != null)
{
currNext = curr.Next;
curr.Next = prev;
prev = curr;
curr = currNext;
}
head = prev;
}
}
internal class SumNumbersLinkedListTest
{
static void Main()
{
SinglyLinkedList num1 = new SinglyLinkedList();
SinglyLinkedList num2 = new SinglyLinkedList();
num1.Insert(6);
num1.Insert(1);
num1.Insert(7);
num2.Insert(2);
num2.Insert(9);
num2.Insert(5);
num1.Print();
num2.Print();
SinglyLinkedList resultReverseSum = new SinglyLinkedList();
SinglyLinkedList resultForwardSum = new SinglyLinkedList();
SinglyLinkedList.SumNumbersReverse(num1, num2, resultReverseSum);
Console.WriteLine("After summing reverse: ");
resultReverseSum.Print();
SinglyLinkedList num3 = new SinglyLinkedList();
SinglyLinkedList num4 = new SinglyLinkedList();
num3.Insert(7);
num3.Insert(1);
num3.Insert(6);
num4.Insert(5);
num4.Insert(9);
num4.Insert(2);
SinglyLinkedList.SumNumbersForward(num3, num4, resultForwardSum);
Console.WriteLine("After summing forward: ");
resultForwardSum.Print();
Console.ReadLine();
}
}
}
答案 4 :(得分:0)
您可以通过撤消链接列表来完成此操作。这是一个c#实现和 这是O(n)。
public LinkedList ElementSum(LinkedList other)
{
LinkedList linkedListSum = new LinkedList();
this.Reverse();
other.Reverse();
Node n1 = this.head, n2 = other.head;
int toAdd = 0, carryOver = 0;
while ((n1 != null) || (n2 != null))
{
int num1 = (int) (n1 == null ? 0 : n1.NodeContent);
int num2 = (int) (n2 == null ? 0 : n2.NodeContent);
toAdd = (num1 + num2 + carryOver) % 10;
carryOver = (int)(num1 + num2 + carryOver) / 10;
linkedListSum.Add(toAdd);
n1 = (n1 == null ? null : n1.Next);
n2 = (n2 == null ? null : n2.Next);
}
this.Reverse();
other.Reverse();
linkedListSum.Reverse();
return linkedListSum;
}