[英]Calculating the Sum of values in a linked list
我最近在接受采訪時得到了一個編程問題。
有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;
}
}
我在這個問題上看到的其他解決方案涉及通過在輸入列表上向后迭代來逐步構建返回的列表,同時在轉到新列表時添加每個元素。 這種方式更復雜,因為你必須添加每個元素並處理結轉。
如果陣列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性質向后迭代。
嗨@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
。 這是一種簡單的方法。
在你要求第一種方法的問題中,給出的例子也是第一種方法,但你的源代碼是第二種方法。 請遵守它。
我看到的其他答案通常依賴額外的堆棧。 實際上它只能用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
,我們就從指針“p1”回退。 我們首先將指針“p2”中的兩個數字分開,然后將正確的數字添加到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) )
。
這是我對這個問題的回答(使用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();
}
}
}
您可以通過反轉鏈接列表來完成此操作。 這是ac#implementation,它是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;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.