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
2009-08-16 00:54:21
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
2009-08-16 05:35:20
+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
2009-08-16 01:24:03
Agreed. This general technique is a good one to know for solving similar problems.
caf
2009-08-16 04:50:27
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?
2009-08-16 23:17:39
@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
2009-08-16 23:35:00
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
2009-08-17 10:02:58
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
2009-08-17 10:18:03
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
2009-08-17 13:09:58
@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
2009-10-16 01:46:37
+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
2009-08-16 15:18:22
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
2009-08-17 13:43:21