【LetMeFly】2563.统计公平数对的数目:排序 + 二分查找 力扣题目链接:https://leetcode.cn/problems/count-the-number-of-fair-pairs/
给你一个下标从 0 开始、长度为 n
的整数数组 nums
,和两个整数 lower
和 upper
,返回 公平数对的数目 。
如果 (i, j)
数对满足以下情况,则认为它是一个 公平数对 :
0 <= i < j < n
,且
lower <= nums[i] + nums[j] <= upper
示例 1:
输入: nums = [0,1,7,4,4,5], lower = 3, upper = 6
输出: 6
解释: 共计 6 个公平数对:(0,3)、(0,4)、(0,5)、(1,3)、(1,4) 和 (1,5) 。
示例 2:
输入: nums = [1,7,9,2,5], lower = 11, upper = 11
输出: 1
解释: 只有单个公平数对:(2,3) 。
提示:
1 <= nums.length <= 105
nums.length == n
-109 <= nums[i] <= 109
-109 <= lower <= upper <= 109
解题方法:排序 + 二分查找 要找的是值在一定范围内的$nums[i] + nums[j]$,且加法满足交换律($a+b=b+a$),所以查找结果和元素顺序无关。
所以只需要遍历$nums$的下标作为$i$,并在$i+1$到数组末尾的范围内查找$j$的范围,最终累加到答案中即可。
如何确定$j$的范围?$upper_bound(upper - i) - lower_bound(lower - i)$或$lower_bound(upper - i + 1) - lower_bound(lower - i)$均可。
其中$lower_bound(t)$是非递减数组中第一个插入$t$后数组仍非递减的下标,$upper_bound(t)$是非递减数组中最后一个插入$t$后数组仍非递减的下标。
时间复杂度$O(n\log n)$,其中$n=len(nums)$
空间复杂度$O(\log n)$
AC代码 C++ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 typedef long long ll;class Solution {public : long long countFairPairs (vector<int >& nums, int lower, int upper) { sort (nums.begin (), nums.end ()); ll ans = 0 ; for (int i = 0 ; i < nums.size (); i++) { ans += upper_bound (nums.begin () + i + 1 , nums.end (), upper - nums[i]) - lower_bound (nums.begin () + i + 1 , nums.end (), lower - nums[i]); } return ans; } };
Python 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ''' Author: LetMeFly Date: 2025-04-19 16:13:37 LastEditors: LetMeFly.xyz LastEditTime: 2025-04-19 16:23:38 ''' from typing import List from bisect import bisect_left, bisect_rightclass Solution : def countFairPairs (self, nums: List [int ], lower: int , upper: int ) -> int : nums.sort() return sum (bisect_right(nums, upper - nums[i], i + 1 ) - bisect_left(nums, lower - nums[i], i + 1 ) for i in range (len (nums)))
Java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 import java.util.Arrays;class Solution { private int search (int [] nums, int x, int l) { int r = nums.length; while (l < r) { int mid = (l + r) >> 1 ; if (nums[mid] >= x) { r = mid; } else { l = mid + 1 ; } } return l; } public long countFairPairs (int [] nums, int lower, int upper) { Arrays.sort(nums); long ans = 0 ; for (int i = 0 ; i < nums.length; i++) { ans += search(nums, upper - nums[i] + 1 , i + 1 ) - search(nums, lower - nums[i], i + 1 ); } return ans; } }
Go 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package mainimport ( "sort" )func countFairPairs (nums []int , lower int , upper int ) (ans int64 ) { sort.Ints(nums) for i, v := range nums { l := sort.Search(len (nums), func (x int ) bool {return x > i && nums[x] >= lower - v}) r := sort.Search(len (nums), func (x int ) bool {return x > i && nums[x] >= upper - v + 1 }) ans += int64 (r - l) } return }
同步发文于CSDN 和我的个人博客 ,原创不易,转载经作者同意后请附上原文链接 哦~
千篇源码题解已开源