2563.统计公平数对的数目 是否顺序无关?
2563.统计公平数对的数目
- 观察这个数据的范围,虽然数据范围很大,但是一共就只有
10^5
个数字,可以考虑通过离散化
把数字的范围控制在3*10^5
,但是对于原来的形式lower <= nums[i] + nums[j] <= upper
,对于一个nums[j]
来说,就得考虑前面的所有的nums[j]
的情况,在这里有一个方法,那就是树状数组,用一个值域树状数组
用于统计这个区间和,但是发现还是无法避免需要一个个统计nums[i],i<j
的情况 - 那么是否可以通过排序,使用二分的算法进行求解?
o(nlong)
,我们通过将公式变形,去证明这个公式是顺序无关的
- 观察这个原来的形式
# lower <= nums[i] + nums[j] <= upper
- 原本的形式是求解在这个
nums[j]
的时候,需要一个个枚举前面的nums[i]
的情况
可以通过移项得到:
#公式1 lower - nums[i] <= nums[j] <= upper - nums[i]#公式2 lower - nums[j] <= nums[i] <= upper - nums[j]
- 这样求解的形式就分开来了,虽然有要求这个
i<j
,但是这个形式就算是我们求解当前的是nums[j]
,它的贡献值是前面的i<j
的全部满足公式1的情况,当然前后是相对的,它对后面的贡献值是满足公式2的全部情况,所以,综合考虑,这个题目的本质只是统计出两个不同位置满足这个公式的数对,所以是顺序无关的
import bisect
class Solution:def countFairPairs(self, nums: List[int], lower: int, upper: int) -> int:# 二分的思路# 转换公式的形式之后,你会发现这是一个顺序无关的问题?为什么?下面的公式是对于i,j都是一样的,也就是只用选出两个数即可# lower - nums[i] <= nums[j] <= upper - nums[i]# lower - nums[j] <= nums[i] <= upper - nums[j]nums.sort()ans = 0for i,num in enumerate(nums):indexl = bisect.bisect_left(nums,lower-num,0,i)index2 = bisect.bisect_right(nums,upper-num,0,i)ans += index2 - indexlreturn ans