简体   繁体   中英

Finding a pair of values which add up to given sum

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

This is the output

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

I don't know why it's being shown up twice. I need to find a pair of values that add up to the given sum and this is the only way I could think of. I only want it to show up once though any ideas on how I can do that?

There are better solutions, but to fix your issue making minimal changes to your code:

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

This will print

3 and 9 is equal to 12

Note that the redundant table is completely removed from the code.

If you run it for a better test case:

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

it will print

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

First, to address why the looping continues and gives a second output, break can only break out of its immediate loop. Since you have a nested loop, the break only stops the for y in table: inner loop, but allows for x in table outer loop to move onto it's next iteration. So eventually, x is able to take the value of 3 later on, thus giving you the two outputs you see.

So, if you need a way to stop the iteration entirely when a solution is found, you need to either chain the break statements using a for else syntax (which arguably might be tough to read) as follows,

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 says: run through the whole iteration, and if no break is found, executes the code in the else block. Essentially, the "else" of a "for else" is like a "for - no break".

However, one easier alternative is to use a function with a return (which also makes it easier to read the code).

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.

Also, you could just repeat the break condition, but repeating code is generally not a good practice.

Hope this helps address why the two outputs are being printed. Now, as for the solution itself, there's actually a much better way to solve this. It builds upon the idea of compliments, which you seem to have a sense of in your table. But it doesn't require iteration over the table itself. As a hint: the ideal solution runs in O(n) time. I will not discuss the ideal solution, but hope this prompts you to find the best approach.

Use itertools to get the result

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

Looping twice for n elements costs you O(N^2) time, which is inefficient for large lists. Modified and tested the code to use hash map/dictionary to store the list elements and now it will take only O(N) time.

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. Store the value of each list element into the map whenever it does not exist in the map.
  2. At each iteration, take the difference between givenSum and current element at that iteration and then search for that difference in the Map.
  3. If it exists it means the pair exists or else not.

In this approach you are running the loop only once, which takes O(N) time because accessing elements in hash map is O(1)/constant time.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM