tags:

views:

487

answers:

3

Do it in N^2, how would one do this

+6  A: 

put the negative of each number into a hash table or some other constant time lookup data structure. (n)

loop through the array getting each set of two numbers (n^2), and see if their sum is in the hash table.

FigBug
This solution will also work for a slightly different question:Are there three/four numbers which sum can be devided by a constant q without remainder?
Anna
+11  A: 

O(n^2) solution without hash tables (because using hash tables is cheating :P). Here's the pseudocode:

Sort the array // O(nlogn)

for each i from 1 to len(array) - 1
  iter = i + 1
  reviter = len(array) - 1
  while iter < reviter
    tmp = array[iter] + array[reviter] + array[i]
    if  tmp > 0
       reviter--
    else if tmp < 0
       iter++
    else 
      return true
return false

Basically using a sorted array, for each number (target) in an array, you use two pointers, one starting from the front and one starting from the back of the array, check if the sum of the elements pointed to by the pointers is >, < or == to the target, and advance the pointers accordingly or return true if the target is found.

Charles Ma
This is way better than the hash table solution
leiz
Agreed. This general technique is a good one to know for solving similar problems.
caf
What is len(n)? Is that the index of target?
hughdbrown
len(n) is the length of the array :)
Charles Ma
hey charles, i have 1 more question. In your code, isn't it possible for the target to be the same as the array[inter] or array[reviter]?So then you are adding the same number twice?
@Ryan: The pseudocode (err, python) I wrote below based on this addresses exactly that: it stops when lower increments to target's index or upper decrements to that point. See the "while lower < i < upper: " loop control. Charles Ma's original code tries to find just the first mathcing instance. The code I wrote finds all unique instances in the integers provided.
hughdbrown
yep, it is possible, so we can first do a check to make sure the index of target, iter, and reviter are not equal. i'll change the code to do that. if you want all possible solutions, hughbrown's code does that :)
Charles Ma
heh, just found some optimizations to get around the problem of the target being the same number as one of the pointed to numbers :)
Charles Ma
You're making the 'target' the lowest number of the triplet and working the two other numbers to be both above and to converge in on each other. The code I wrote based on your original description has the 'target' as the middle element and has the two others work from below 0 and len-1 to converge in the middle on 'target'. I think it produces the same answers.
hughdbrown
@Charles Ma: Hey, Charles, check how I re-used my python code to answer this question: http://stackoverflow.com/questions/1560523/onlogn-algorithm-find-three-evenly-spaced-ones-within-binary-string/1576044#1576044
hughdbrown
+2  A: 

Not for credit or anything, but here is my python version of Charles Ma's solution. Very cool.

def find_sum_to_zero(arr):
    arr = sorted(arr)
    for i, target in enumerate(arr):
     lower, upper = 0, len(arr)-1
     while lower < i < upper:
      tmp = target + arr[lower] + arr[upper]
      if tmp > 0:
       upper -= 1
      elif tmp < 0:
       lower += 1
      else:
       yield arr[lower], target, arr[upper]
       lower += 1
       upper -= 1

if __name__ == '__main__':
    # Get a list of random integers with no duplicates
    from random import randint
    arr = list(set(randint(-200, 200) for _ in range(50)))
    for s in find_sum_to_zero(arr):
     print s
hughdbrown
I love how python looks just like pseudocode!
Charles Ma
maybe it does to python coders, not to me. :p
Jason S
If you want an explanation, here are the non-obvious bits for a non-python developer:(1) enumerate returns each element of a sequence with its integer index, starting from 0(2) "lower < i < upper" means "lower < i and i < upper" in a single test(3) yield returns a value from a function but allows execution to continue from that point the next time it is requested(4) set() returns a group of unique items, dumping multiple occurrences(5) multiple variables can be assigned in a single statement(6) the generator statement says, "Give me 50 integers in the range -200 to 200
hughdbrown