2

Given a list of integers, l = [1,5,3,2,6] and a target t = 6, return true if the list contains two distinct integers that sum to the target

I was given this question on a technical Python interview that caused me not to pass. My answer was:

def two_Sum(l, target):
  for num in l:
    for secondNum in l:
      if num != secondNum:
        if num + secondNum == target:
          return True

The feedback I was given was that my solution was "not optimal". Please help me to understand why this was not the optimal solution and explain in detail what would be optimal for this case!

wim
  • 338,267
  • 99
  • 616
  • 750

5 Answers5

3

Your solution has a nested loop iterating the list, which means it's O(n^2) time complexity - and O(1) space, since you don't need to store any data during the iteration.

Reducing to O(n) time complexity is possible like this, coming at the cost of increasing to O(n) space complexity:

def two_sum(l, target):
    s = set(l)
    for n in l:
        delta = target - n
        if delta != n and delta in s:
            return True
    return False

As a slight improvement, you can even avoid to traverse the entire list, but it's still O(n):

def two_sum(l, target):
    seen = set()
    for n in l:
        delta = target - n
        if delta != n and delta in seen:
            return True
        seen.add(n)
    return False
wim
  • 338,267
  • 99
  • 616
  • 750
1

you can start by having two pointers (start,end), start will point to start of the list and end will point to end of list, then add them and see if it equals to your target, if equals then print or add to result.

if sum is greater then your target that means decrease your end pointer by 1 and if it's equal to or smaller than your target then increase your start pointer.

def two_Sum(l,target):
    start=0
    end=len(l)-1
    while start!=end:
        pair_sum=l[start]+l[end]
        if pair_sum==target:
            print l[start],l[end]

        if pair_sum <= target:
            start=start+1

        if pair_sum > target:
            end = end-1


l=[1,2,3,4,5,6,7,8,9,10]


two_Sum(l,9)
wim
  • 338,267
  • 99
  • 616
  • 750
pushpendra chauhan
  • 2,205
  • 3
  • 20
  • 29
0

This will only go once through your list:

def two_sum(l, t):
  s = set(l)
  for n in s:
    if t-n in s:
      if n != t-n:
        return True
  return False
mvp
  • 111,019
  • 13
  • 122
  • 148
0

The most efficient way is to hash T-I[i] for each i and check each element as you see it

def sum2(I,T):
   h = {}
   for itm in I:
      if itm in h:
          return True
      h[T-itm] = 1
   return False
dfb
  • 13,133
  • 2
  • 31
  • 52
  • 1
    Maybe `set` instead of `dict` would be more appropriate semantically. – grovina Nov 29 '17 at 05:28
  • This one also gives incorrect results for some of the edge cases – wim Nov 29 '17 at 05:33
  • @wim - Care to share? – dfb Nov 29 '17 at 05:35
  • @wim I dont see the point in saying that this code fails for some edge cases, but don't even share what they are? – RoadRunner Nov 29 '17 at 06:17
  • See the line `if num != secondNum` in OP code ... this one didn't address the requirement to find two *distinct* integers. – wim Nov 29 '17 at 16:12
  • @wim - The way this problem is usually given is distinct is used in the sense of repeating a single element (I=[4], T=8 returns false) rather than adding two of the same number (I=[4,4], T=8 returns false) – dfb Nov 29 '17 at 17:07
  • Naturally, but then the problem must be specified like "two distinct elements" or "two different indices" and not "two distinct integers". – wim Nov 29 '17 at 17:13
-1

Your solution is O(n²), as you do a nested iteration of the whole list.

A simple solution with time complexity n log(n) would be:

  • sort your list
  • iterate doing a binary search for the complementary to target

Supposing you have binary search implemented in function bs(item, sorted_list):

def two_Sum(l, target):
    l_sorted = sorted(l)  # n log(n)
    return any(bs(target - x, l_sorted) for x in l_sorted)  # n log(n)

You can also do some other optimisation like stop iterating if you reach target/2.

Caveat: I don't garantee nor really believe this is the optimal solution, but rather intended to show you a better one and give insight to your improving your own.

grovina
  • 2,999
  • 19
  • 25