LeetCode 2563.统计公平数对的数目:排序 + 二分查找

【LetMeFly】2563.统计公平数对的数目:排序 + 二分查找

力扣题目链接:https://leetcode.cn/problems/count-the-number-of-fair-pairs/

给你一个下标从 0 开始、长度为 n 的整数数组 nums ,和两个整数 lowerupper ,返回 公平数对的数目

如果 (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

解题方法:排序 + 二分查找

要找的是值在一定范围内的 n u m s i + n u m s j numsi + numsj numsi+numsj,且加法满足交换律( a + b = b + a a+b=b+a a+b=b+a),所以查找结果和元素顺序无关。

所以只需要遍历 n u m s nums nums的下标作为 i i i,并在 i + 1 i+1 i+1到数组末尾的范围内查找 j j j的范围,最终累加到答案中即可。

如何确定 j j j的范围? u p p e r _ b o u n d ( u p p e r − i ) − l o w e r _ b o u n d ( l o w e r − i ) upper\_bound(upper - i) - lower\_bound(lower - i) upper_bound(upper−i)−lower_bound(lower−i)或 l o w e r _ b o u n d ( u p p e r − i + 1 ) − l o w e r b o u n d ( l o w e r − i ) lower\_bound(upper - i + 1) - lower_bound(lower - i) lower_bound(upper−i+1)−lowerbound(lower−i)均可。

其中 l o w e r b o u n d ( t ) lower_bound(t) lowerbound(t)是非递减数组中第一个插入 t t t后数组仍非递减的下标, u p p e r b o u n d ( t ) upper_bound(t) upperbound(t)是非递减数组中最后一个插入 t t t后数组仍非递减的下标。

  • 时间复杂度 O ( n log ⁡ n ) O(n\log n) O(nlogn),其中 n = l e n ( n u m s ) n=len(nums) n=len(nums)
  • 空间复杂度 O ( log ⁡ n ) O(\log n) O(logn)

AC代码

C++
cpp 复制代码
/*
 * @Author: LetMeFly
 * @Date: 2025-04-19 15:51:42
 * @LastEditors: LetMeFly.xyz
 * @LastEditTime: 2025-04-19 16:12:44
 */
/*
l: first j 满足 nums[j] + nums[i] >= lower | nums[j] >= lower - nums[i]
r: last  j 满足 nums[j] + nums[i] <= upper | nums[j] <= upper - nums[i]

l: lower_bound(lower - nums[i])
r: upper_bound(upper - nums[i])
*/
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]);
            // cout << i << ": " << i << "[" << lower_bound(nums.begin() + i + 1, nums.end(), lower - nums[i]) - nums.begin() << ", " << upper_bound(nums.begin() + i + 1, nums.end(), upper - nums[i]) - nums.begin() << ')' << endl;
        }
        return ans;
    }
};
Python
python 复制代码
'''
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_right


class 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
java 复制代码
/*
 * @Author: LetMeFly
 * @Date: 2025-04-19 16:24:08
 * @LastEditors: LetMeFly.xyz
 * @LastEditTime: 2025-04-19 16:37:36
 */
import java.util.Arrays;

class Solution {
    private int search(int[] nums, int x, int l) {  // search [l, len(nums)) 范围内第一个大于等于x的下标
        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
go 复制代码
/*
 * @Author: LetMeFly
 * @Date: 2025-04-19 16:24:24
 * @LastEditors: LetMeFly.xyz
 * @LastEditTime: 2025-04-19 16:43:06
 */
package main
import (
    "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和我的个人博客,原创不易,转载经作者同意后请附上原文链接哦~

千篇源码题解已开源

相关推荐
tkevinjd2 小时前
MiniCode 项目详解6:原项目控制系统的10个缺陷(已修复)
python·llm·agent
dNGUZ7UGj3 小时前
10分钟完成第一个Python小游戏
python·django
2601_954526753 小时前
【工业传感与算法实战】温漂补偿与零点抗漂破局:基于二阶多项式拟合的 C/C++ 边缘校准算法,深度拆解“压力变送器什么牌子好”的技术硬指标
c语言·c++·算法
没有梦想的咸鱼185-1037-16633 小时前
AI-Python机器学习与深度学习技术:CNN/Transformer/扩散模型、SHAP可解释及Hermes智能体自动化
人工智能·python·深度学习·机器学习·chatgpt·cnn·transformer
霸道流氓气质4 小时前
SpringBoot中通用工具类库(Utils)封装与使用实践
spring boot·后端·python
叩码以求索4 小时前
浅谈:算法萌新如何高效刷题应对面试(一)
算法·面试·职场和发展
Draina5 小时前
CBC填充预言攻击-CBC Padding Oracle Crypto Attack
python·安全·web安全·网络安全·密码学·安全性测试
c238566 小时前
把 C++ 内存分配拆透:new 与 malloc 的三层血缘
开发语言·c++·算法
Angel Q.6 小时前
特征提取 | DINO 到 DINOv3
图像处理·python
不如语冰6 小时前
AI大模型入门-pytorch-张量2 tensor创建
python