【问题标题】:Finding a pair of values which add up to given sum找到一对加起来等于给定总和的值
【发布时间】:2020-06-12 05:42:59
【问题描述】:
lst = [3, 4, 1, 2, 9]

givenSum = 12
table = {}
x = 0
y = 0

for i in range(0, len(lst)):
    table[givenSum - lst[i]] = 1
    i += 1

for x in table:
    for y in table:
        if (x + y) == givenSum:
            print(x, "and", y, "is equal to", givenSum)
            break

这是输出

9 and 3 is equal to 12
3 and 9 is equal to 12

我不知道为什么它会出现两次。我需要找到一对加起来等于给定总和的值,这是我能想到的唯一方法。我只希望它显示一次,尽管我有什么想法可以做到这一点?

【问题讨论】:

  • 使用break 不输出超过一个。 (你也无用地检查反向;break 会有所帮助,但它会比它需要的慢。)
  • 如果列表中有6,你会怎么做?
  • 要解决重复问题,只需将if (x + y) == givenSum: break 添加到外循环

标签: python arrays sorting dictionary for-loop


【解决方案1】:

有更好的解决方案,但要解决您的问题,只需对代码进行最少的更改:

lst = [3, 4, 1, 2, 9]
givenSum = 12

for x in range(0, len(lst) - 1):
    for y in range(x + 1, len(lst)):
        if lst[x] + lst[y] == givenSum:
            print(lst[x], "and", lst[y], "is equal to", givenSum)
            break

这将打印出来

3 and 9 is equal to 12

请注意,多余的table 已从代码中完全删除。

如果你运行它以获得更好的测试用例:

lst = [3, 4, 5, 6, 7, 1, 2, 9]

它会打印出来

3 and 9 is equal to 12
5 and 7 is equal to 12

【讨论】:

  • 这样做还有一个好处是,如果lst中有一个6,就不用说6 and 6 is equal to 12
  • @Nick 没错。我在第二个测试列表中特别包含了6
【解决方案2】:

首先,为了解决循环继续并给出第二个输出的原因,break 只能跳出其直接循环。由于您有一个嵌套循环,break 仅停止for y in table: 内部循环,但允许for x in table 外部循环移动到下一次迭代。所以最终,x 稍后能够获取3 的值,从而为您提供您看到的两个输出。

因此,如果您需要一种在找到解决方案时完全停止迭代的方法,您需要使用for else 语法(可能很难阅读)链接break 语句,如下所示,

for x in table:
    for y in table:
        if (x + y) == givenSum:
            print(x, "and", y, "is equal to", givenSum)
            break #breaks from inner loop
    else: #for else syntax: this block runs if and only if there was no break encountered during looping.
        continue #jumps the outer loop to next iteration
    break #this break is set at outer loop's level. Essentially, we can only reach this portion if there is a break in the inner loop.

for else 表示:运行整个迭代,如果没有找到中断,则执行 else 块中的代码。本质上,“for else”的“else”就像“for - no break”。

但是,一种更简单的替代方法是使用带有return 的函数(这也使代码更容易阅读)。

def find_given_sum(lst, givenSum):
    table = {}
    x = 0
    y = 0

    for i in range(0, len(lst)):
        table[givenSum - lst[i]] = 1
        i += 1

    for x in table:
        for y in table:
            if (x + y) == givenSum:
                print(x, "and", y, "is equal to", givenSum)
                return #this returns immediately out of the function, thus stopping the iteration.

另外,您可以重复中断条件,但重复代码通常不是一个好习惯。

希望这有助于解决打印两个输出的原因。现在,至于解决方案本身,实际上有一个更好的方法来解决这个问题。它建立在恭维的概念之上,你似乎在你的桌子上有一种感觉。但它不需要对表本身进行迭代。作为提示:理想的解决方案在O(n) 时间运行。我不会讨论理想的解决方案,但希望这能促使您找到最佳方法。

【讨论】:

  • 你根本不需要table,但是为了论证,你为什么不把table传递给函数呢?请注意,如果lst 中有一个元素等于givenSum 的一半,这两种方法都会失败。
  • @Selcuk 因为我做出了一个有意识的决定,为了 OP 的利益而专注于观察到的行为的“原因”,而不是仅仅给出最佳答案。 (编辑:我也考虑在这个桶的一部分纠正边缘情况。决定不关注它)。至于为什么我没有将 table 传递给函数,只是因为该逻辑是 OP 解决方案的一部分,因此它确实应该与现有函数 imo 捆绑在一起。
  • tl;博士,我想解释一下为什么 OP 看到他们看到的行为,仅此而已。
【解决方案3】:

为 n 个元素循环两次会花费 O(N^2) 时间,这对于大型列表来说效率很低。修改并测试了代码以使用哈希映射/字典来存储列表元素,现在只需 O(N) 时间。

Map = dict()
lst = [3, 4, 1, 2, 9]
givenSum = 12

for i in range(0, len(lst)):
    rem=givenSum-lst[i]
    if rem in Map:
        print lst[i],lst[Map[rem]]
    else:
        Map[lst[i]]=i
  1. 只要每个列表元素的值在地图中不存在,就将其存储到地图中。
  2. 在每次迭代中,获取 givenSum 和当前元素在该迭代中的差值,然后在 Map 中搜索该差值。
  3. 如果存在,则表示该对存在或不存在。

在这种方法中,您只运行一次循环,这需要 O(N) 时间,因为访问哈希映射中的元素是 O(1)/恒定时间。

【讨论】:

    【解决方案4】:

    使用itertools获取结果

    import itertools
    sum = 10
    lst = [3, 4, 1, 2, 9]
    ans = list(filter(lambda x : x[0]+x[1] == sum,itertools.combinations(lst, 2)))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-11
      • 1970-01-01
      相关资源
      最近更新 更多