【问题标题】:Find two numbers from a list that add up to a specific number从列表中找到两个加起来为特定数字的数字
【发布时间】:2018-08-27 15:18:03
【问题描述】:

这是超级糟糕和混乱,我是新手,请帮助我。

基本上,我试图从一个列表中找到两个加起来为目标数字的数字。

我已经使用lst = [2, 4, 6, 10] 和目标值target = 8 设置了一个示例。这个例子中的答案是(2, 6)(6, 2)

以下是我的代码,但它又长又丑,我相信有更好的方法。您能看看我如何从下面的代码中改进吗?

from itertools import product, permutations

numbers = [2, 4, 6, 10]
target_number = 8

two_nums = (list(permutations(numbers, 2)))
print(two_nums)

result1 = (two_nums[0][0] + two_nums[0][1])
result2 = (two_nums[1][0] + two_nums[1][1])
result3 = (two_nums[2][0] + two_nums[2][1])
result4 = (two_nums[3][0] + two_nums[3][1])
result5 = (two_nums[4][0] + two_nums[4][1])
result6 = (two_nums[5][0] + two_nums[5][1])
result7 = (two_nums[6][0] + two_nums[6][1])
result8 = (two_nums[7][0] + two_nums[7][1])
result9 = (two_nums[8][0] + two_nums[8][1])
result10 = (two_nums[9][0] + two_nums[9][1])

my_list = (result1, result2, result3, result4, result5, result6, result7, result8, result9, result10)
print (my_list)

for i in my_list:
  if i == 8:
print ("Here it is:" + str(i))

【问题讨论】:

  • 44 在您的示例中是一个解决方案吗?
  • 这不是更适合CodeGolfCode Review论坛吗?
  • @Ev.Kounis,是的,但在这种情况下,我尽量不添加它的编号。
  • 您的代码几乎完全针对问题。如果列表的长度不同怎么办?你的代码不起作用。像这样命名一堆特定的变量几乎不是一个好主意。您需要以有组织的、通用的方式进行。为了让您入门,请尝试以下操作:for a, b in permutations(numbers, 2):。顺便说一句:这里使用组合更合适,因为加法的顺序无关紧要。
  • 别担心,这是一个常见的错误,像你一样尝试用permutations(或组合)做一些事情实际上是一个很好的 Pythonic 方法,很多新人不会不考虑。为了将来参考(不一定针对这个问题),制作大量这样的变量的正确方法涉及制作一个名为例如的列表。 result 然后将值放入result[0]result[1] 等等。

标签: python for-loop permutation


【解决方案1】:

对于列表中的每个数字,您可以查找他的补数(当添加到前一个数字时,将给出所需的target 总和)。如果存在,则获取该对并退出,否则继续。

如下所示:

numbers = [2, 4, 6, 10]
target_number = 8

for i, number in enumerate(numbers[:-1]):  # note 1
    complementary = target_number - number
    if complementary in numbers[i+1:]:  # note 2
        print("Solution Found: {} and {}".format(number, complementary))
        break
else:  # note 3
    print("No solutions exist")

产生:

Solution Found: 2 and 6

注意事项:

  1. 您不必检查最后一个数字;如果有一对,到那时你就已经找到了。
  2. 请注意,成员检查(在列表中成本很高)已优化,因为它只考虑切片 numbers[i+1:]。以前的数字已经检查过了。切片的一个积极副作用是,例如,列表中存在一个 4,不会给出目标值 8 的一对。
  3. 这是一个很好的设置来解释elsefor-loops 中的错误理解和经常令人困惑的用法。仅当循环未被break 突然结束时,else 才会触发。


如果您可以接受例如4 - 4 解决方案,即使列表中有单个 4,您可以进行如下修改:

numbers = [2, 4, 6, 10]
target_number = 8

for i, number in enumerate(numbers):
    complementary = target_number - number
    if complementary in numbers[i:]:
        print("Solution Found: {} and {}".format(number, complementary))
        break
else:
    print("No solutions exist")

【讨论】:

  • 这太不可思议了,让我花点时间吸收,非常感谢!也感谢你给我 4-4 的解决方案。
  • @moomoochen 尽情享受,如果有任何问题,我会很乐意回答。干杯。
【解决方案2】:

列表推导在这里可以很好地工作。试试这个:

from itertools import permutations

numbers = [2, 4, 6, 10]
target_number = 8

solutions = [pair for pair in permutations(numbers, 2) if sum(pair) == 8]
print('Solutions:', solutions)

基本上,这个列表解析会查看permutations(numbers, 2) 返回的所有对,但只保留总和等于8 的对。

【讨论】:

    【解决方案3】:

    执行此操作的最简单的通用方法是遍历您的列表,并为每个项目遍历列表的其余部分以查看它是否与目标值相加。这样做的缺点是它是一个 O(n^2) 操作。我不知道是否有更有效的解决方案。我不是 100% 确定我的语法是正确的,但它应该如下所示:

    done = False
    for i, val in enumerate(numbers):
        if val >= target_number:
            continue
        for j, val2 in enumerate(numbers, i+1):
            if val + val2 == target_number:
                print ("Here it is: " + str(i) + "," + str(j))
                done = True
                break
        if done:
            break
    

    当然,您应该将其创建为一个返回结果的函数,而不仅仅是打印它。这将消除对“完成”变量的需要。

    【讨论】:

    • 我会评论我自己的解决方案,@kounis 提出的解决方案要好一些。它的效率并不高(它和我的代码做同样的事情),但它做得更优雅、更紧凑(就代码量而言)。它还可以处理负数,而我的则不能。
    【解决方案4】:

    如果您试图找到具有重复值的长列表的多个整数的答案,我建议使用frozenset。 “已检查”的答案只会得到第一个答案,然后停止。

    import numpy as np
    numbers = np.random.randint(0, 100, 1000)
    target = 17
    
    def adds_to_target(base_list, target):
        return_list = []
        for i in range(len(base_list)):
            return_list.extend([list((base_list[i], b)) for b in base_list if (base_list[i] + b)==target])
        return set(map(frozenset, return_list))
    
    # sample output
    {frozenset({7, 10}),
     frozenset({4, 13}),
     frozenset({8, 9}),
     frozenset({5, 12}),
     frozenset({2, 15}),
     frozenset({3, 14}),
     frozenset({0, 17}),
     frozenset({1, 16}),
     frozenset({6, 11})}
    

    1) 在第一个 for 循环中,将包含两个总和为目标值的整数的列表添加到“return_list”,即创建一个列表列表。

    2) 然后frozenset取出所有重复的pair。

    %timeit adds_to_target(numbers, target_number)
    # 312 ms ± 8.86 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
    

    【讨论】:

      【解决方案5】:

      你可以用下面的列表理解在一行中完成:

      from itertools import permutations
      
      numbers = [2, 4, 6, 10]
      target_number = 8
      two_nums = (list(permutations(numbers, 2)))
      
      result=[i for i in two_nums if i[0]+i[1] == target_number]
      

      [(2,6) , (6,2)]

      【讨论】:

      • 这可能是效率最低的方法,需要 O(n^2) 的额外空间。
      • @StevenW.Klassen 真的!对 python 新手来说似乎最平易近人
      【解决方案6】:

      如果你想在没有 itertools 的情况下有效地做到这一点 -

      numbers = [1,3,4,5,6,2,3,4,1]
      target = 5
      number_dict = {}
      pairs = []
      for num in numbers:
          number_dict[num] = number_dict.get(num, 0) + 1
          complement = target - num
          if complement in number_dict.keys():
              pairs.append((num, complement))
              number_dict.pop(num)
              number_dict.pop(complement)
      

      【讨论】:

        【解决方案7】:

        就是这么简单:)

        def func(array, target):
            flag = 0;
            for x in array:
                for y in array:
                    if (target-x) == y and x != y:
                        print(x,y)
                        flag = 1
                        break
                if flag ==1:
                    break
        

        【讨论】:

          【解决方案8】:
          import pandas as pd
          
          Filename = "D:\\python interview\\test.txt"
          wordcount_dict = dict()
          #input("Enter Filename:") 
          
          list_ = [1,2,4,6,8]
          num = 10
          
          for number in list_:
              num_add = number
              for number_ in list_:
                  if number_ + num_add == num and number_ != num_add :
                      print(number_ , num_add)
          

          【讨论】:

            【解决方案9】:

            n 是所需的总和,L 是列表。基本上,您进入循环内部,然后从“否”到列表末尾迭代下一个循环。如果 L[i],L[j] 列表中的索引加起来为 n 并且如果 L[i]!=L[j] 打印它。

            numbers=[1,2,3,4,9,8,5,10,20,30,6]
            def two_no_summer(n,L):
                 for i in range(0,len(L)):
                     for j in range(i,len(L)):
                         if (L[i]+L[j]==n) & (L[i]!=L[j]):
                              print(L[i],L[j])
            

            执行:https://i.stack.imgur.com/Wu47x.jpg

            【讨论】:

            • 请对您的代码进行一些解释
            • 缩进不正确会抛出语法错误
            • 修正语法、缩进和添加描述。希望它现在可以工作
            猜你喜欢
            • 2020-06-06
            • 1970-01-01
            • 1970-01-01
            • 2016-01-16
            • 2015-11-09
            • 2023-01-07
            • 2018-12-20
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多