-1

I am not sure how to do this. Given a list of numbers and a number k, return all pairs of numbers from the list that add up to k. only pass through the list once.

For example, given [10, 15, 3, 7] and k of 17. The program should return 10 + 7.

How do you order and return every pair while only going through the list once.

  • 5
    Possible duplicate of [Find two numbers from a list that add up to a specific number](https://stackoverflow.com/questions/52042370/find-two-numbers-from-a-list-that-add-up-to-a-specific-number) – ruakh Apr 02 '19 at 00:25
  • Are there constraints on the numbers? If `k` is reasonably small and all the numbers fall within some bounds (e.g. if they're all nonnegative) then you can do something like a counting sort. – manveti Apr 02 '19 at 00:33
  • @ruakh the linked problem is indeed the same, but it includes the `python` tag, and all answers are python-specific. Linking it is fine, but it is no duplicate. – tucuxi Apr 02 '19 at 10:56

2 Answers2

2

Use a set to keep track of what you've seen. Runtime O(N), Space: O(N)

def twoAddToK(nums, k):
  seen = set()
  N = len(nums)
  for i in range(N):
    if k - nums[i] in seen:
      return True
    seen.add(nums[i])  
  return False
Shawn
  • 7,235
  • 6
  • 33
  • 45
  • Note that resizing the hash table means that `set.add` ultimately works out to linear complexity, rather than constant, across arbitrarily many calls, so this solution is quadratic unless the range of values is limited. – manveti Apr 02 '19 at 00:54
  • 2
    set.add is amortized O(1) – Shawn Apr 02 '19 at 00:57
  • Hmm... now that I look at the code, it seems to me that the worst case is actually exponential: if the first two numbers inserted are 0 and 8, and each subsequent value is the previous value times 4, the table will resize with each insert (after 50000 you only have to double the value each time to trigger the resize). Each resize in that case is proportional to the value being inserted. Granted, that's quite a pathological case designed to break the specific implementation... – manveti Apr 02 '19 at 01:25
  • how do you know the set is implemented as a hash table? It isn't clear to me that Runtime is O(N), maybe O(N*log(N)), but the solution isn't quadratic either – SaraVF Apr 02 '19 at 10:03
  • @CraigMeier most hash table implementations grow based on capacity not what keys are being inserted. I would recommend building a naive one -- It would probably be around 50 lines of code. – Shawn Apr 02 '19 at 12:09
  • The cPython implementation (https://github.com/python/cpython/blob/master/Objects/setobject.c) is somewhat more than 50 lines -- enough that I missed the linear probing case, which makes it so targeting hash collisions at 0 as I did above won't work quite so well. But I still think pathological input can get a hash collision every time after some constant number of inserts. – manveti Apr 02 '19 at 17:05
  • @CraigMeier, you're talking about amortized worst case, I'm talking about worst case. Anyway, it's not a bad solution, it's just that for some specific cases the spent time would be quadratic – SaraVF Apr 05 '19 at 17:11
0

As an alternative to Shawn's code, which uses a set, there is also the option of sorting the list in O(N log N) time (and possibly no extra space, if you are allowed to overwrite the original input), and then applying an O(N) algorithm to solve the problem on a sorted list

While asymptotic complexity slightly favors using hash sets in terms of time, since O(N) is better than O(N log N), I am ready to bet that sorting + single-pass lookup is considerably faster in practice.

tucuxi
  • 17,561
  • 2
  • 43
  • 74