Reputation: 181
I am trying to solve a problem of finding all the pairs of a list that have a sum of k, in 0(nlogn) time.
I first sort the list (I use merge sort) and then do binary search for each element x of the array to look for (k-x). This works for regular lists, but for example if I have a list like [1,1,1,1] and k=2, my code returns 4 instead of 6. I was wondering if there is any variation of binary search that allows for the above to happen. I tried googling around but I couldn't find anything that covered this question.
For reference this is my code ( I did not include merge sort since it's not relevant)
def binary_search(alist, item):
if len(alist)==0:
return False
else:
mid=len(alist)//2
if alist[mid]==item:
return True
else:
if item< alist[mid]:
return binary_search(alist[:mid], item)
else:
return binary_search(alist[mid+1:], item)
def find_pairs(alist, k):
count=0
for i in range(len(alist)):
if binary_search(alist,(k-alist[i])):
count+=1
return(count)
Upvotes: 0
Views: 122
Reputation: 60944
I think you can do this in O(n)
time and O(n)
space.
def num_pairs(arr, k):
counts = Counter(arr)
total = 0
for item, count in counts.items():
diff = k - item
if diff in counts and (diff < item or (diff==item and count>1)):
if diff == item:
total += (count*(count-1))//2
else:
total += count*counts[diff]
return total
Here we make a mapping of each number to the number of times it occurs in the input. For each entry we look up the complement in mapping, and can then compute the number of such pairs using arithmetic.
Upvotes: 0
Reputation: 2087
Since you want to do it with Binary Search:
x
, binary search for (k-x)
in the remaining list. If found, add aux[index(x)]*aux[index(k-x)]
to result.Additional step:
For the case that you have mentioned, if k
is even, look for k/2
. If present, add Combination(aux[index(k/2)], 2)
to the result.
All this should be within nlogn. Also, you can achieve the same without much hassle using Python Dictionaries.
Upvotes: 1