Skip to content

Commit 933cc3c

Browse files
committed
feat(algorithms, two-pointers): count pairs
1 parent a2071a2 commit 933cc3c

19 files changed

+201
-69
lines changed
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# Count Pairs Whose Sum is Less than Target
2+
3+
You are given a 0-indexed integer array, nums, of length n, and an integer target. Your task is to determine the number
4+
of distinct pairs of indexes (i,j) such that:
5+
6+
- 0≤i<j<n (i.e., i comes before j in the array)
7+
- The sum of the elements of the indexes (i,j), (i.e., nums[i]+nums[j]), is strictly less than the target.
8+
9+
## Constraints
10+
11+
- n == `nums.length`
12+
- 1 <= n <= 50
13+
- -50 <= nums[i], `target` <= 50
14+
15+
## Examples
16+
17+
![Example 1](./images/examples/count_pairs_example_1.png)
18+
![Example 2](./images/examples/count_pairs_example_2.png)
19+
![Example 3](./images/examples/count_pairs_example_3.png)
20+
![Example 4](./images/examples/count_pairs_example_4.png)
21+
22+
## Topics
23+
24+
- Array
25+
- Two Pointers
26+
- Sorting
27+
- Binary Search
28+
29+
## Solution
30+
31+
The problem requires counting the number of valid pairs in an array where the sum of the pair is less than a given target.
32+
To solve this efficiently, we first sort the array to simplify pair comparisons. After sorting, we initialize two pointers:
33+
one at the beginning of the array and the other at the end. Sorting ensures that any element at a higher index is greater
34+
than or equal to the element at a lower index, allowing us to evaluate pairs in a structured manner. The two pointer
35+
approach leverages this property to efficiently identify valid pairs.
36+
37+
When the sum of the elements at the two positions is smaller than the given target, all pairs formed by fixing the lower
38+
position and combining it with values starting from the higher position down to the lower position are valid. This is
39+
because the sequence is sorted, and any pair created by moving the higher position downward results in a smaller sum,
40+
which is guaranteed to be less than the current sum of the two positions. The total number of such valid pairs is the
41+
difference between the higher and lower positions.
42+
43+
After counting these pairs, the lower position is incremented to check combinations involving larger values, allowing us
44+
to explore pairs with higher sums. If the sum of the elements at the two positions is not smaller than the given target,
45+
the higher position is moved backward to reduce the sum and potentially find valid pairs. This approach ensures efficient
46+
counting of all valid pairs without redundant checks.
47+
48+
The steps of the algorithm are as follows:
49+
1. Sort the input array, `nums`, in an ascending order.
50+
2. Initialize a variable `count` to 0 to keep track of the total number of valid pairs. Also, initialize two pointers,
51+
`low` and `high`, with `low` at the beginning of the array and `high` at the end.
52+
3. Use the pointers to traverse the array until `low < high`, and check the sum of `nums[low] + nums[high]`:
53+
- If the sum is less than the target, all `low` and `high` (inclusive of high) pairs are valid because the array is
54+
sorted. Add `high - low` to `count`. Increment low to explore additional valid pairs with a larger first element.
55+
- Otherwise, decrement `high` to reduce the sum.
56+
4. Once the pointers meet or cross, the iteration ends.
57+
5. Return the value of `count` as the total number of valid pairs.
58+
59+
![Solution 1](./images/solutions/count_pairs_solution_1.png)
60+
![Solution 2](./images/solutions/count_pairs_solution_2.png)
61+
![Solution 3](./images/solutions/count_pairs_solution_3.png)
62+
![Solution 4](./images/solutions/count_pairs_solution_4.png)
63+
![Solution 5](./images/solutions/count_pairs_solution_5.png)
64+
![Solution 6](./images/solutions/count_pairs_solution_6.png)
65+
![Solution 7](./images/solutions/count_pairs_solution_7.png)
66+
![Solution 8](./images/solutions/count_pairs_solution_8.png)
67+
![Solution 9](./images/solutions/count_pairs_solution_9.png)
68+
![Solution 10](./images/solutions/count_pairs_solution_10.png)
69+
70+
71+
### Time Complexity
72+
73+
The time complexity analysis is as follows:
74+
75+
- **Sorting the array**: The array is sorted at the beginning, which takes `O(n log(n))`, where n is the number of
76+
elements in the array.
77+
78+
- **Two pointer traversal**: The algorithm uses a single loop for the two pointer approach, which runs in `O(n)`.
79+
80+
Add these complexities together: `O(n log(n)) + O(n) = O(n log(n))`. Thus, the overall time complexity is `O(nlog(n))`.
81+
82+
### Space Complexity
83+
84+
The algorithm’s space complexity is O(n) because it creates a new list to store the sorted elements, while the
85+
two-pointer traversal only requires a constant amount of extra space.
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
from typing import List
2+
3+
4+
def count_pairs(nums: List[int], target: int) -> int:
5+
"""
6+
Counts the number of pairs of numbers in a list that sum to a value less than a target.
7+
Uses a two-pointer approach to find the pairs, with a time complexity of O(n log n).
8+
Modifies the list in place to sort the numbers.
9+
Args:
10+
nums (List[int]): A list of integers
11+
target (int): The target value to search for
12+
Returns:
13+
int: The number of pairs of numbers in the list that sum to a value less than the target
14+
"""
15+
# Get the length of the numbers
16+
n = len(nums)
17+
18+
# Validation check, if there are less than 2 numbers, return 0. We can't form a pair here
19+
if n < 2:
20+
return 0
21+
22+
# Sort the nums in place, this incurs a time complexity of O(n log n)
23+
nums.sort()
24+
25+
# Initialize the left and right pointers
26+
left, right = 0, n - 1
27+
28+
# Initialize the count of pairs
29+
count = 0
30+
31+
# Use a while loop to find the pairs
32+
while left < right:
33+
# Get the current sum of the numbers at the left and right pointers
34+
current_sum = nums[left] + nums[right]
35+
# If the sum is less than the target, then the numbers in between the left and right pointers
36+
# form valid pairs with the left pointer
37+
if current_sum < target:
38+
# Count the pairs
39+
count += right - left
40+
# Move the pointer up to find other distinct pairs
41+
left += 1
42+
else:
43+
# move the pointer down to find other pairs, reducing the sum of the boundary
44+
right -= 1
45+
46+
# Return the count of pairs
47+
return count
39.5 KB
Loading
33 KB
Loading
38.7 KB
Loading
25.3 KB
Loading
20.2 KB
Loading
26.9 KB
Loading
32 KB
Loading
27.5 KB
Loading

0 commit comments

Comments
 (0)