找到两个数组的总和

3

我正在尝试在Python中找到两个列表/数组的总和。

例如:

你有两个随机整数列表lst1lst2,分别具有大小nm。这两个列表都包含来自0到9的数字(即每个索引处都存在单个数字)。

这里的想法是将每个列表表示为一个由N和M位数字组成的整数。

您需要找到输入列表的总和,将它们视为两个整数,并将结果放入另一个列表中,即输出列表在每个索引处也仅包含单个数字。

以下是我尝试的代码:

def list_sum(lst1, n, lst2, m) :
    i, j, sum, carry = 0, 0, 0, 0
    new_lst = []
    if n == 0 and m == 0:
        new_lst.append(0)
    elif n > 0 and m>0:
        while n > 0 and m > 0:
            sum = lst1[n - 1] + lst2[m - 1] + carry
            if sum >= 10:
                carry = 1
            else:
                carry = 0
            new_lst.append(sum % 10)
            n -= 1
            m -= 1
        while n > 0:
            if (lst1[n-1] + carry) >= 10:
                new_lst.append((lst1[n-1] + carry) % 10)
                carry = 1
            else:
                new_lst.append(lst1[n-1])
                carry = 0
            n -= 1
        while m > 0:
            if (lst2[m-1] + carry) >= 10:
                new_lst.append((lst2[m-1] + carry) % 10)
                carry = 1
            else:
                new_lst.append(lst1[m-1])
                carry = 0
            m -= 1
        if carry == 1:
            new_lst.append(1)
        new_lst.reverse()
    elif n == 0 and m > 0:
        new_lst.append(0)
        new_lst = new_lst + lst2
    elif n > 0 and m == 0:
        new_lst.append(0)
        new_lst = new_lst + lst1
    print(new_lst)

然而,我感觉我在这里缺少了某些东西,这不给我正确的组合答案。有时会出现索引错误的错误列表。我不知道为什么。
示例输入:
n = 3
lst1 = [6, 9, 8] 
m = 3
lst2 = [5, 9, 2]

输出:

[1, 2, 9, 0]

这里,每个元素都被加起来,如果 sum >= 10,那么我们就会得到一个 carry = 1,并且它将与下一个 sum 相加。

也就是说

1. 8+2= 10 >=10 hence carry=1 in first sum
2. 9+9+1( carry) = 19 >=10 hence carry=1
3. 6+5+1( carry) = 12>=10 hence carry=1
4. upend the carry to next position as 1
Hence resultant list would be [1, 2, 9, 0]

我该尝试什么?


3
什么问题?你的代码对于给定的输入有效。 - BrokenBenchmark
有时会出现索引错误的错误列表..我不知道为什么..是否有其他更简洁且执行时间更短的解决方案? - Humble_PrOgRaMeR
2
它在哪些输入上会抛出这个错误? - BrokenBenchmark
1
我看到一个列表的一个实例“由另一个索引索引”。(典型的复制和粘贴错误。“仅携带”部分是没有必要重复的,而且过于复杂。)一旦错误被修复,请考虑Code Review@SE - greybeard
为了找出代码的问题,您需要进行调试。这篇文章提供了一些很好的提示,可以帮助您入门。 - Code-Apprentice
既然你有大量的建议,如果你能将它们进行比较并发布结果以供文档记录,那就太好了。 - deponovo
7个回答

3

其他答案都很适用于将2个数字(数字列表)相加。
但是,如果你想要创建一个可以处理任意数量“数字”的程序

以下是你可以做的...

def addNums(lst1, lst2, *args):
    numsIters = [iter(num[::-1]) for num in [lst1, lst2] + list(args)]  # make the iterators for each list
    carry, final = 0, []                                                # Initially carry is 0, 'final' will store the result
    
    while True:
        nums = [next(num, None) for num in numsIters]                   # for every num in numIters, get the next element if exists, else None
        if all(nxt is None for nxt in nums): break                      # If all numIters returned None, it means all numbers have exhausted, hence break from the loop
        nums = [(0 if num is None else num) for num in nums]            # Convert all 'None' to '0'
        digit = sum(nums) + carry                                       # Sum up all digits and carry
        final.append(digit % 10)                                        # Insert the 'ones' digit of result into final list
        carry = digit // 10                                             # get the 'tens' digit and update it to carry

    if carry: final.append(carry)                                       # If carry is non-zero, insert it
    return final[::-1]                                                  # return the fully generated final list

print(addNums([6, 9, 8], [5, 9, 2]))                                    # [1, 2, 9, 0]
print(addNums([7, 6, 9, 8, 8], [5, 9, 2], [3, 5, 1, 7, 4]))             # [1, 1, 2, 7, 5, 4]


希望这讲得清楚明白!

1
我认为注释并不能真正解释代码。它们基本上只是重复了已经写在同一行上的内容,只是稍微详细一些。[next(num, None) for num in numsIters] # for every num in numIters, get the next element if exists, else None 这个注释解释了"for"是一个for循环,并且"next"函数获取下一个元素? sum(nums) + carry # Sum up all digits and carry 是的,我能读懂这个。 - Stef
你有final.insert(0, digit % 10)。这使得你的代码效率远不如它本应该有的那样高。在列表的位置0插入需要重写整个列表。另一种选择是提前猜测最终列表的大小;或者将数字附加到末尾而不是开头,然后在return之前反转列表。 - Stef
1
对于复杂性部分,我同意并已经做出了改变,但是谈论到注释部分,不同的人喜欢不同风格的注释。对于有经验的程序员来说可能不需要,但是那些新手程序员会非常需要对这些代码行的解释,因此每行都进行注释可以确保每个程序员,无论是新手还是有经验的,都能从中受益。 - HIMANSHU PANDEY
我同意你的代码会因为解释而受益匪浅。但是,总结函数整体功能的几个注释比每行重复该行操作的注释更有帮助。显然,“digit = sum(nums) + carry”计算了nums的总和,然后加上进位。重复这一点的注释毫无帮助。有用的注释应该涉及到整个函数,这将使人们更容易理解为什么在这个点上计算nums的总和并添加进位是有帮助的。 - Stef
def addNums(lst1, lst2, *args): 可以被替换为 def addNums(*args):,而 numsIters = [iter(num[::-1]) for num in [lst1, lst2] + list(args)] 可以被替换为 numsIters = [iter(num[::-1]) for num in args] 以简化代码。 - Bibhav
你没有理解为什么要放置两个显式参数。它背后的主旨是确保用户在函数调用中至少提供了2个数字,以便调用函数具有一定意义,否则仅针对1个数字调用函数毫无意义。你也可以在编程语言中检查其他类似的方法,它们都遵循相同的类比! - HIMANSHU PANDEY

1
如果我理解正确,您希望它像这样: [6, 9, 8],[5, 9, 2] -> 698 + 592 = 1290 -> [1, 2, 9, 0]
在这种情况下,我的第一个想法是将数字转换为字符串,将它们组合成一个字符串,然后将其转换为整数,再将两个值相加并再次转换为整数列表……您可以尝试这个:
def get_sum_as_list(list1, list2):
    first_int = int(''.join(map(str,list1)))
    second_int = int(''.join(map(str,list2)))
    result = [int(num) for num in str(first_int+second_int)]
    return result

我尝试了这个解决方案,但问题是,如果任何一个列表的大小为零,则需要在结果列表的开头附加0。 - Humble_PrOgRaMeR
如果其中一个列表为空,那么你只需要返回另一个列表吗?还是你想要其他的东西。基本上,你可以在函数开始时检查空列表,比如 'if not list1: return list2' 和 'if not list2: return list1'。 - user17824666
1
@PujariRajagonda,你可以使用first_int = reduce(lambda x,y: 10*x+y, list1, 0)代替first_int = int(''.join(map(str,list1)))。这样可以避免转换为str并处理空列表的情况。其中reducefrom functools import reduce - Stef
1
@Stef 有趣。这比我预期的竞争力更持久。 - Kelly Bundy

1
以下是可能的解决方案:
(i)将每个列表连接起来,创建一对整数字符串表示形式
(ii)将它们转换为整数,
(iii)相加,
(iv)将总和转换为字符串
(v)将每个数字分开作为整数
def list_sum(lst1, lst2):
    out = []
    for i, lst in enumerate([lst1, lst2]):
        if len(lst) > 0:
            out.append(int(''.join(str(x) for x in lst)))
        else:
            if i == 0:
                return lst2
            else:
                return lst1
    return [int(x) for x in str(out[0]+out[1])]

list_sum([6,9,8],[5,9,2])

输出:

[1, 2, 9, 0]

1

尝试了以下逻辑

def list_sum(lst1, n, lst2, m, output):
i, j, k, carry = n - 1, m - 1, max(n, m), 0
while i >= 0 and j >= 0:
    output[k] = (lst1[i] + lst2[j] + carry) % 10
    carry = (lst1[i] + lst2[j] + carry) // 10
    i = i - 1
    j = j - 1
    k = k - 1
while i >= 0:
    output[k] = (lst1[i] + carry) % 10
    carry = (lst1[i] + carry) // 10
    i = i - 1
    k = k - 1
while j >= 0:
    output[k] = (lst2[j] + carry) % 10
    carry = (lst2[j] + carry) // 10
    j = j - 1
    k = k - 1
output[0] = carry
print(output)

在上面的代码中,输出参数取自下面的位置。
outputSize = (1 + max(n, m))
output = outputSize * [0]

并调用该函数
list_sum(lst1, n, lst2, m, output)

1

您没有提及列表的长度。考虑到它们不会太长(反正Python可以处理大数),为什么不进行简单的求和操作呢?最终代码应该模拟这个操作。

import numpy as np
lst1 = [6, 9, 8] 
lst2 = [5, 9, 2]
lst1_len = len(lst1)
lst2_len = len(lst2)
if lst1_len >= lst2_len:
    lst2 = [0] * (lst1_len - lst2_len) + lst2
else:
    lst1 = [0] * (lst2_len - lst1_len) + lst1

common_len = len(lst1)

lst1_val = sum(np.array(lst1) * np.array([10**(-x) for x in range(-common_len + 1, 1)]))
lst2_val = sum(np.array(lst2) * np.array([10**(-x) for x in range(-common_len + 1, 1)]))
total = lst1_val + lst2_val
total_as_list = [int(x) for x in str(total)]

在哪里

print(total_as_list)
[1, 2, 9, 0]

1

另外两个答案展示了重复转换整数列表和字符串以及整数之间的解决方案。我认为这有点作弊,并完全隐藏了算法。

在这里,我提供了一种直接操作整数列表来构建第三个整数列表的解决方案。

from itertools import chain, repeat # pad list with 0 so they are equal size
from operator import add            # add(x,y) = x+y

def padded(l1, l2):
    "padded([1, 2, 3], [1, 2, 3, 4, 5]) --> [0, 0, 1, 2, 3], [1, 2, 3, 4, 5]"
    padded1 = chain( repeat(0, max(0, len(l2)-len(l1))), l1 )
    padded2 = chain( repeat(0, max(0, len(l1)-len(l2))), l2 )
    return padded1, padded2

def add_without_carry_same_size(l1, l2):
    "add_without_carry([6, 9, 8], [5, 9, 2]) --> [11, 18, 10]"
    return map(add, l1, l2)

def flatten_carry(l):
    "flatten_carry([11, 18, 10]) --> [1, 2, 9, 0]"
    c = 0
    for i in range(len(l)-1, -1, -1):
        c, l[i] = divmod(c + l[i], 10)
    if c > 0:
        l[:] = [c] + l

def list_add(l1, l2):
    '''
    list_add([6, 9, 8], [5, 9, 2]) --> [1, 2, 9, 0]
    list_add([9, 9, 9, 9, 9], [1]) --> [1, 0, 0, 0, 0, 0]
    '''
    p1, p2 = padded(l1, l2)
    l3 = list(add_without_carry_same_size(p1, p2))
    flatten_carry(l3)
    return l3

相关文档:


0

代码:

def addNums(*args):
    nums=[]
    for i in args:                                
        if i:
            i = list(map(str,i))               # Converts each element int to string['6', '9', '8'] , ['5', '9', '2']
            add=int(''.join(i))                # Joins string and convert to int  698 ,592
            nums.append(add)                   # Appends them to list [698, 592]

    Sum = str(sum(nums))                       # Sums the values and convert to string '1290'
    result=list(map(int,Sum))                  # Converts to list with each converted to int[1,2,9,0]
    
    return result
print(addNums([6, 9, 8], [5, 9, 2]))  
print(addNums([7, 6], [5, 9], [3, 5],[7, 4]))
print(addNums([]))

输出:

[1, 2, 9, 0]
[2, 4, 4]
[0]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接