Leetcode 2563. Count the Number of Fair Pairs
Table of Contents
Problem Informations
- Problem Index: 2563
- Problem Link: Count the Number of Fair Pairs
- Topics: Array, Two Pointers, Binary Search, Sorting
Problem Description
Given a 0-indexed integer array nums of size $n$ and two integers lower and upper, return the number of fair pairs.
A pair (i, j) is fair if:
- $0 \leq i < j < n$, and
- $lower \leq nums[i] + nums[j] \leq upper$
Example 1:
Input: nums = [0,1,7,4,4,5], lower = 3, upper = 6
Output: 6
Explanation: There are 6 fair pairs: (0,3), (0,4), (0,5), (1,3), (1,4), and (1,5).
Example 2:
Input: nums = [1,7,9,2,5], lower = 11, upper = 11
Output: 1
Explanation: There is a single fair pair: (2,3).
Constraints:
- $1 \leq nums.length \leq 10^5$
- $nums.length == n$
- $-10^9 \leq nums[i] \leq 10^9$
- $-10^9 \leq lower \leq upper \leq 10^9$
Intuition
The problem asks us to determine how many pairs of indices in the array satisfy a certain condition on their summed values. A straightforward approach would be to use two nested loops to sum all pairs and check which sums fall within the specified bounds. However, this naive approach would be inefficient for large arrays due to its $\mathcal{O}(n^2)$ complexity. Thus, a more efficient method involves sorting the array and exploiting binary search to significantly reduce the number of comparisons needed to count fair pairs.
Approach
The solution leverages a sorted array to efficiently count pairs of indices whose sums fall within a specified range. The steps are as follows:
Initialization: Start with an empty list,
previousNumbers, to keep track of numbers processed so far in sorted order, and a counter,fairPairCount, initialized to zero.Iterate through the array: For each element
numin the given arraynums:Binary Search for Range: Use binary search to determine the range of numbers in
previousNumbersthat can form a fair pair withnum. Specifically, use:lower_boundto find the first element inpreviousNumbersthat, when added tonum, results in a sum not less thanlower.upper_boundto find the first element inpreviousNumbersthat, when added tonum, results in a sum greater thanupper.
Count Valid Indices: The difference between the
upper_boundandlower_bounditerators gives the number of valid indices inpreviousNumbersthat satisfy the condition.
Insert and Maintain Order: Insert the current
numintopreviousNumbersin a position that maintains the list’s sorted order. This step ensurespreviousNumbersis ready for the next iteration.Return Count: After processing all elements,
fairPairCountwill contain the total number of fair pairs.
By maintaining a sorted list of previously processed numbers and using binary search to efficiently find bounds within this list, we reduce the problem of counting fair pairs to a task manageable in $\mathcal{O}(n \log n)$ time complexity. This significant reduction is achieved by combining sorting, binary search, and clever use of data structures, which together provide a scalable solution to the problem.
Code
C++
class Solution {
public:
long long countFairPairs(vector<int>& nums, int lower, int upper) {
vector<int> previousNumbers;
long long fairPairCount = 0;
for (int num : nums) {
// Find the lower bound: first element not less than (lower - num)
vector<int>::iterator lowerBoundIt = lower_bound(previousNumbers.begin(), previousNumbers.end(), lower - num);
// Find the upper bound: first element greater than (upper - num)
vector<int>::iterator upperBoundIt = upper_bound(previousNumbers.begin(), previousNumbers.end(), upper - num);
// Calculate the number of elements in the range [lower - num, upper - num]
fairPairCount += upperBoundIt - lowerBoundIt;
// Insert 'num' in the sorted position within 'previousNumbers'
previousNumbers.insert(upper_bound(previousNumbers.begin(), previousNumbers.end(), num), num);
}
return fairPairCount;
}
};
Python
class Solution:
def countFairPairs(self, nums, lower, upper):
previousNumbers = []
fairPairCount = 0
for num in nums:
# Find the lower bound: first element not less than (lower - num)
lowerBoundIt = self.lower_bound(previousNumbers, lower - num)
# Find the upper bound: first element greater than (upper - num)
upperBoundIt = self.upper_bound(previousNumbers, upper - num)
# Calculate the number of elements in the range [lower - num, upper - num]
fairPairCount += upperBoundIt - lowerBoundIt
# Insert 'num' in the sorted position within 'previousNumbers'
previousNumbers.insert(self.upper_bound(previousNumbers, num), num)
return fairPairCount
def lower_bound(self, nums, target):
left, right = 0, len(nums)
while left < right:
mid = (left + right) // 2
if nums[mid] < target:
left = mid + 1
else:
right = mid
return left
def upper_bound(self, nums, target):
left, right = 0, len(nums)
while left < right:
mid = (left + right) // 2
if nums[mid] <= target:
left = mid + 1
else:
right = mid
return left
Complexity
Time complexity: The time complexity is $O(n \log n)$. This is because for each element in the input vector
nums, we perform alower_boundandupper_boundoperation on the vectorpreviousNumbers, both of which take $O(\log n)$ time in the worst case since the vector is maintained in sorted order. Additionally, inserting an element into the sorted vectorpreviousNumbersusingupper_boundalso takes $O(\log n)$ time. Since there are $n$ elements innums, the overall time complexity is $O(n \log n)$.Space complexity: The space complexity is $O(n)$. This is because we use an auxiliary vector
previousNumbersto store the numbers seen so far in sorted order, which in the worst case can contain up to all $n$ elements from the input vectornums. Therefore, the space complexity is $O(n)$.
Disclaimer: All reference materials on this website are sourced from the internet and are intended for learning purposes only. If you believe any content infringes upon your rights, please contact me at csnote.cc@gmail.com, and I will remove the relevant content promptly.
Feedback Welcome: If you notice any errors or areas for improvement in the articles, I warmly welcome your feedback and corrections. Your input will help this blog provide better learning resources. This is an ongoing process of learning and improvement, and your suggestions are valuable to me. You can reach me at csnote.cc@gmail.com.