【Leetcode 每日一题】2563. 统计公平数对的数目
问题背景
给你一个下标从 0 0 0 开始、长度为 n n n 的整数数组 n u m s nums nums,和两个整数 l o w e r lower lower 和 u p p e r upper upper,返回 公平数对的数目 。
如果 ( i , j ) (i, j) (i,j) 数对满足以下情况,则认为它是一个 公平数对 :
- 0 ≤ i < j < n 0 \le i < j < n 0≤i<j<n,且
- l o w e r ≤ n u m s [ i ] + n u m s [ j ] ≤ u p p e r lower\le nums[i] + nums[j] \le upper lower≤nums[i]+nums[j]≤upper
数据约束
- 1 ≤ n u m s . l e n g t h ≤ 1 0 5 1 \le nums.length \le 10 ^ 5 1≤nums.length≤105
- n u m s . l e n g t h = n nums.length = n nums.length=n
- − 1 0 9 ≤ n u m s [ i ] ≤ 1 0 9 -10 ^ 9 \le nums[i] \le 10 ^ 9 −109≤nums[i]≤109
- − 1 0 9 ≤ l o w e r ≤ u p p e r ≤ 1 0 9 -10 ^ 9 \le lower \le upper \le 10 ^ 9 −109≤lower≤upper≤109
解题过程
对于任意一个 n u m s [ j ] nums[j] nums[j],能与它构成公平数对的 n u m s [ i ] nums[i] nums[i] 范围是 l o w e r − n u m s [ i ] ≤ n u m s [ j ] ≤ u p p e r − n u m s [ i ] lower - nums[i] \le nums[j] \le upper - nums[i] lower−nums[i]≤nums[j]≤upper−nums[i]。
由于题目要求只是从数组中挑选两个数字,数组中元素的顺序不影响最终的结果,可以先排序,用二分查找。
具体实现
class Solution {public long countFairPairs(int[] nums, int lower, int upper) {Arrays.sort(nums);long res = 0;for (int i = 0; i < nums.length; i++) {int right = binarySearch(nums, i, upper - nums[i] + 1);int left = binarySearch(nums, i, lower - nums[i]);res += right - left;}return res;}private int binarySearch(int[] nums, int right, int target) {int left = 0;while (left < right) {int mid = left + ((right - left) >>> 1);if (nums[mid] < target) {left = mid + 1;} else {right = mid;}}return left;}
}