【问题标题】:using two variable in for loop for list operations在 for 循环中使用两个变量进行列表操作
【发布时间】:2021-03-06 04:39:17
【问题描述】:

我希望我的输出是 [i, j] 其中 list[i] + list[j] 等于目标值。例如;

nums=[2,7,11,15]

目标=9

输出=[0,1] 作为 num[0]+num[1]==target 的总和

我尝试了我的代码代码为;

nums=[2,7,11,15]
target=9
b=len(nums)
for i,j in zip(range(b),range(b)):
    if nums[i]+nums[j]==target:
        print(i,j)

我想返回列表中元素的位置,其总和等于期望值,我上面的代码没有输出期望值,解决这个问题的最佳方法是什么?

【问题讨论】:

    标签: python python-3.x list for-loop list-comprehension


    【解决方案1】:

    您希望针对i 的每个值考虑j 的所有值。 zip() 不这样做,它只考虑每个列表中的对齐对,即 ij 的匹配值。你需要一个嵌套循环,像这样:

    nums=[2,7,11,15]
    target=9
    b=len(nums)
    for i in range(b):
        for j in range(b):
            if nums[i]+nums[j]==target:
                print(i,j)
    

    您可以通过使用enumerate() 将索引和值放在一起来简化它:

    nums=[2,7,11,15]
    target=9
    for i, n in enumerate(nums):
        for j, m in enumerate(nums):
            if m + n == target:
                print(i,j)
    

    有多种方法可以加快速度:

    您可以只考虑大于或等于ij 索引,然后在匹配时打印出i, jj, i

    如果您知道nums 已排序,则可以通过使用从底部向上计数并从顶部向下计数的while 循环使其更快。这将在找到匹配项时报告匹配项,并在总和太低时升高底部计数器,或在总和太高时降低顶部计数器。

    如果nums 没有排序,像@deepak-tripathi 这样的基于字典的解决方案将是最有效的。该解决方案和移位边界解决方案都有 O(n) 解决方案时间(与嵌套循环的 O(n^2) 相比)并且基于字典的解决方案更容易正确编写(例如处理重复值)并且可以处理排序或未排序的列表..

    【讨论】:

      【解决方案2】:

      看看zip()做了什么:

      list(zip(range(4), range(4)))
      
      [(0, 0), (1, 1), (2, 2), (3, 3)]

      您没有迭代所有组合,只是 i = j 的情况。试试itertools 模块,它为这种情况提供了许多高效的迭代器。

      import itertools
      
      
      nums=[2,7,11,15]
      target=9
      b=len(nums)
      for i,j in itertools.combinations(range(b), 2):
          if nums[i]+nums[j]==target:
              print(i,j)
      

      https://docs.python.org/3/library/itertools.html#itertools.combinations

      【讨论】:

      • 非常感谢您提供这个非常有用的答案
      【解决方案3】:

      您必须使用嵌套的 for 循环。

      nums = [2, 7, 11, 15]
      target = 9
      b = len(nums)
      
      for i in range(b - 1):
          for j in range(i + 1, b):
              if nums[i] + nums[j] == target:
                  print(i, j)
      

      如果列表很大或性能很重要,您可以对此类问题进行很多优化。例如,在上面的代码中,首先对列表进行排序,从小数开始。如果nums[i] > target,则从外部迭代中中断,如果nums[i] + nums[j] > target,则从内部迭代中中断。

      【讨论】:

        【解决方案4】:

        我认为这个问题可以使用这样的字典来解决: 我已经打印了元素,你也可以得到索引

        d_ = {}
        nums=[2,7,11,15]
        val  =None
        
        for i in nums:
          if d_.get(i):
            d_[i] += 1
          else:
            d_[i] = 1
        
        target = 17
        for i in nums:
          if d_.get(target-i, None):
            val = (i,target-i)
            break
        
        if val:
          print(nums.index(val[0]))
          print(nums.index(val[1]))
        

        【讨论】:

        • 您的解决方案简单高效,但并不完全正确,因为它显示的是匹配值而不是它们的索引。在您当前的版本中,您可以将两个d_.get() 调用替换为i in d_。此外,您可以使用集合代替字典,并以set(nums) 快​​速创建集合。或者,如果您想显示索引而不是值,您可以更改当前代码以将索引列表存储在 d_ 中,而不是匹配值的计数。然后您可以在第二个循环中检索并打印这些索引。
        • @MatthiasFripp 我在描述中提到我已经打印了值。现在我已经进行了更改以获取索引。
        【解决方案5】:

        j 增加nums[j+1]zip(range(b),range(b-1))

        nums=[2,7,11,15]
        target=9
        b=len(nums)
        for i,j in zip(range(b),range(b-1)):
            if nums[i]+nums[j+1]==target:
                print(i,j+1)
        

        【讨论】:

        • 它只适用于连续对,如果我的目标是2+11=13,它不会起作用
        • 知道了。谢谢
        猜你喜欢
        • 1970-01-01
        • 2020-08-05
        • 1970-01-01
        • 1970-01-01
        • 2021-06-09
        • 1970-01-01
        • 2019-09-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多