🔗 leetcode.com/problems/co…
题目
- 给定数组 nums,寻找有多少个 (i, j) 对,满足 i < j && lower ≤ nums[i] + nums[j] ≤ upper
思路
- 排序 nums,固定 nums[i],查找 j,满足 i < j && lower ≤ nums[i] + nums[j] ≤ upper 时,j 的最小值 min 和最大值 max,此时可以添加的 pair 对就是 max - min + 1 个
- 查询 j 的最小值,就是查找 nums 中,nums[j] ≥ lower - nums[i] 的 j 的最小值,二分朝 left 逼近
- 查询 j 的最大值,就是超着 nums 中,nums[j] ≤ upper - nums[i] 的 j 的最大值,二分朝 right 逼近
踩坑
- 二分找 j 的最大值时,注意此时 mid 取值应该为 mid = ((l + r) >> 1) + ((l + r) & 1),注意括号,才能不死循环,找寻到 nums[j] ≤ upper - nums[i] 的最大值
代码
class Solution {
public:
int lower_bound(vector<int>& nums, int i, int lower) {
//printf("i %d lower ", i)
lower = lower - nums[i]
int l = i + 1
int r = nums.size()-1
if (nums[r] < lower) return -1
while (l < r) {
int mid = (l + r) >> 1
if (nums[mid] < lower) l = mid + 1
else r = mid
}
return l
}
int upper_bound(vector<int>& nums, int i, int upper) {
//printf("i %d upper ", i)
upper = upper - nums[i]
int l = i + 1
int r = nums.size() -1
if (nums[l] > upper) return -1
while (l < r) {
int mid = ((l + r) >> 1) + ((l + r) & 1)
if (nums[mid] > upper) r = mid -1
else l = mid
}
return l
}
long long countFairPairs(vector<int>& nums, int lower, int upper) {
sort(nums.begin(), nums.end())
long long ans = 0
for (int i = 0
int l = lower_bound(nums, i, lower)
int r = upper_bound(nums, i, upper)
if (l != -1 && r != -1) ans += r - l + 1
}
return ans
}
}