【问题标题】:Find the sum of two arrays求两个数组之和
【发布时间】:2022-01-08 04:26:31
【问题描述】:

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

例如:

给你两个随机整数列表lst1lst2,大小分别为nm。这两个列表都包含来自0 to 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 并将与下一个总和相加。

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]

请帮助我解决这个问题。

【问题讨论】:

  • 有什么问题?您的代码适用于给定的输入。
  • 有时它会从索引错误中列出错误。我不知道为什么。还有其他更简洁且执行时间更短的解决方案吗?
  • 在哪些输入上会引发此错误?
  • 我看到一个列表的一个实例“被另一个索引索引”。 (一个典型的复制和粘贴错误。“仅携带”部分是不必要地复制的,而且无论如何都过于复杂。)一旦错误得到修复,请考虑Code Review@SE
  • 要找出你的代码有什么问题,你需要调试它。 This article 有一些很棒的技巧可以帮助您入门。

标签: python python-3.x list algorithm


【解决方案1】:

嗯,所有其他答案都非常适合添加 2 个数字(数字列表)。
但如果你想create a program which can deal with any number of 'numbers'

您可以这样做...

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]

希望这是有道理的!

【讨论】:

  • 我认为 cmets 对理解代码并没有真正的帮助。他们基本上只是在重复已经写在同一行的内容,只是稍微冗长一些。 [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 是的,我能读懂。
  • 你有final.insert(0, digit % 10)。这会使您的代码效率大大降低。在列表的位置 0 插入需要重写整个列表。另一种方法是提前猜测最终列表的大小;或在末尾而不是开头附加数字,然后在 return 之前反转列表。
  • 对于复杂性部分我同意并进行了更改,但谈到评论部分,不同的人更喜欢不同框架的 cmets。有经验的程序员可能不需要它,但那些刚接触它的人会非常需要对这些行进行一些解释,因此对每一行进行注释可以确保每个程序员,无论是新手还是经验丰富的程序员,都会从中受益。跨度>
  • 我同意您的代码将从解释中受益匪浅。但是,用几个 cmets 来总结该函数作为一个整体的作用要比每行一个注释重复该行在上下文之外的作用要有用得多。很明显digit = sum(nums) + carry 正在计算 nums 的总和,然后加上进位。写一个重复的评论根本没有帮助。对整个函数进行评论会有所帮助,这将使您更容易理解为什么要计算 nums 的总和并在此时添加进位。
  • 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] 以使其更简单。
【解决方案2】:

如果我理解正确,您希望这样: [6, 9, 8], [5, 9, 2] -> 698 + 592 = 1290 -> [1, 2, 9, 0]

在这种情况下,我的第一个想法是将数字转换为字符串,将它们组合成一个字符串 并将其转换为 int,然后将两个值相加并再次转换为整数列表... 你可以试试这个:

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。
  • 如果其中一个列表为空,那么您是否只需要返回另一个列表?或者你想要别的东西。基本上你可以在函数的开头检查空列表,比如'if not list1:return list2'和'if not list2:return list1'
  • @PujariRajagonda 你可以用first_int = int(''.join(map(str,list1))) 代替first_int = reduce(lambda x,y: 10*x+y, list1, 0)。这避免了转换为str 并处理空列表的情况。其中reducefrom functools import reduce
  • @Stef 有趣。保持竞争力的时间比我预期的要长。
【解决方案3】:

这是一种可能的解决方案:

(i)join为每个列表创建一对整数的字符串表示

(ii) 将它们转换为整数,

(iii) 添加它们,

(iv) 将总和转换为字符串

(v) 将每个数字分隔为ints

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]

【讨论】:

    【解决方案4】:

    另外两个答案显示了在 int 列表与字符串和 int 之间重复转换的解决方案。我觉得这有点作弊,完全隐藏了算法。

    这里我提出了一个解决方案,它直接操纵整数列表来构建第三个整数列表。

    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
    

    相关文档:

    【讨论】:

      【解决方案5】:

      尝试了以下逻辑

      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)
      

      【讨论】:

        【解决方案6】:

        你没有提到你的列表会有多长。所以考虑到它们不会那么长(无论如何,python 可以处理 bignums),为什么不做一个简单的求和运算呢?最后,这就是代码应该模拟的内容。

        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]
        

        【讨论】:

          【解决方案7】:

          代码:

          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]
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-01-10
            • 1970-01-01
            • 2015-04-30
            • 1970-01-01
            相关资源
            最近更新 更多