4
\$\begingroup\$

I want to find the number of the pairs in an array that equal a given sum.

I've naively tried to implement brute force as a solution, but it is too slow and this task should not take more than one second.

def getPairsCount(numbers, shouldEqualTo):
 count = 0
 for i in range(len(numbers)):
 for j in range(i + 1, len(numbers)):
 if numbers[i] + numbers[j] == shouldEqualTo:
 count += 1
 return count
asked Dec 4, 2017 at 23:15
\$\endgroup\$
1
  • \$\begingroup\$ What are pairs in this situation? Do they have to be next to each other? Do 3 in a row count as 1 pair, 2 pairs or none? \$\endgroup\$ Commented Dec 5, 2017 at 0:19

2 Answers 2

4
\$\begingroup\$

If you can use extra space :

# O(n) running time / O(n) memory
def get_pair_count(nums, target_sum):
 count = {}
 for num in nums:
 count[num] = count.get(num, 0) + 1
 total_double = 0
 for num in nums:
 complement = target_sum - num
 if complement in count:
 total_double += count[complement]
 if complement == num:
 total_double -= 1
 return total_double // 2

source : http://www.geeksforgeeks.org/count-pairs-with-given-sum/

If you can't use more space you could try this version I just made (at your own risk)

 # O(n log n) running time / O(1) memory
def get_pair_count_no_extra_memory(nums, target_sum):
 nums.sort()
 start = 0
 end = len(nums) - 1
 total = 0
 while start < end:
 current_sum = nums[start] + nums[end]
 if current_sum == target_sum:
 start_count = 1
 end_count = 1
 special_case = False
 if nums[start] == nums[end]:
 special_case = True
 while start+1 < len(nums) and nums[start] == nums[start+1]:
 start_count += 1
 start += 1
 while end-1 >= 0 and nums[end] == nums[end-1]:
 end_count += 1
 end -= 1
 if special_case:
 total += ((start_count - 1) * start_count) // 2
 else:
 total += start_count * end_count
 start += 1
 end -= 1
 elif current_sum < target_sum:
 start += 1
 else:
 end -= 1
 return total
answered Dec 5, 2017 at 1:23
\$\endgroup\$
1
  • 1
    \$\begingroup\$ You could use collections.Counter for the count dictionary . \$\endgroup\$ Commented Dec 5, 2017 at 13:04
2
\$\begingroup\$
  • A stylistic comment first. It will not give you a performance boost, but nevertheless: for i in range() is very non-Pythonic. Consider

    for x in numbers:
     for y in numbers:
     if x + y == target:
     ....
    
  • As for performance, sort your numbers first, and for each number x search for a range taken by target - x. It can be done in a logarithmic time.

answered Dec 5, 2017 at 0:27
\$\endgroup\$
2
  • 2
    \$\begingroup\$ Hmm, for i in range() is very Pythonic, for i in range(len(A)): A[i] however isn't... Also your first gives incorrect output, I'm sure you know, but it's worth mentioning. \$\endgroup\$ Commented Dec 5, 2017 at 0:32
  • 2
    \$\begingroup\$ Also, sorting is n*log(n), not log(n), unless I'm mistaken. \$\endgroup\$ Commented Dec 5, 2017 at 13:05

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.