Skip to content

Commit d70b2f0

Browse files
committed
update: 添加问题“2563.统计公平数对的数目”的代码和题解(#889)
Signed-off-by: LetMeFly666 <[email protected]>
1 parent 056044d commit d70b2f0

7 files changed

+274
-2
lines changed

.commitmsg

Lines changed: 0 additions & 2 deletions
This file was deleted.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* @Author: LetMeFly
3+
* @Date: 2025-04-19 15:51:42
4+
* @LastEditors: LetMeFly.xyz
5+
* @LastEditTime: 2025-04-19 16:12:44
6+
*/
7+
#if defined(_WIN32) || defined(__APPLE__)
8+
#include "_[1,2]toVector.h"
9+
#endif
10+
11+
/*
12+
l: first j 满足 nums[j] + nums[i] >= lower | nums[j] >= lower - nums[i]
13+
r: last j 满足 nums[j] + nums[i] <= upper | nums[j] <= upper - nums[i]
14+
15+
l: lower_bound(lower - nums[i])
16+
r: upper_bound(upper - nums[i])
17+
*/
18+
typedef long long ll;
19+
class Solution {
20+
public:
21+
long long countFairPairs(vector<int>& nums, int lower, int upper) {
22+
sort(nums.begin(), nums.end());
23+
ll ans = 0;
24+
for (int i = 0; i < nums.size(); i++) {
25+
ans += upper_bound(nums.begin() + i + 1, nums.end(), upper - nums[i]) - lower_bound(nums.begin() + i + 1, nums.end(), lower - nums[i]);
26+
// 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;
27+
}
28+
return ans;
29+
}
30+
};
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* @Author: LetMeFly
3+
* @Date: 2025-04-19 16:24:24
4+
* @LastEditors: LetMeFly.xyz
5+
* @LastEditTime: 2025-04-19 16:43:06
6+
*/
7+
package main
8+
import (
9+
"sort"
10+
)
11+
12+
func countFairPairs(nums []int, lower int, upper int) (ans int64) {
13+
sort.Ints(nums)
14+
for i, v := range nums {
15+
l := sort.Search(len(nums), func(x int) bool {return x > i && nums[x] >= lower - v})
16+
r := sort.Search(len(nums), func(x int) bool {return x > i && nums[x] >= upper - v + 1})
17+
ans += int64(r - l)
18+
}
19+
return
20+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* @Author: LetMeFly
3+
* @Date: 2025-04-19 16:24:08
4+
* @LastEditors: LetMeFly.xyz
5+
* @LastEditTime: 2025-04-19 16:37:36
6+
*/
7+
import java.util.Arrays;
8+
9+
class Solution {
10+
private int search(int[] nums, int x, int l) { // search [l, len(nums)) 范围内第一个大于等于x的下标
11+
int r = nums.length;
12+
while (l < r) {
13+
int mid = (l + r) >> 1;
14+
if (nums[mid] >= x) {
15+
r = mid;
16+
} else {
17+
l = mid + 1;
18+
}
19+
}
20+
return l;
21+
}
22+
public long countFairPairs(int[] nums, int lower, int upper) {
23+
Arrays.sort(nums);
24+
long ans = 0;
25+
for (int i = 0; i < nums.length; i++) {
26+
ans += search(nums, upper - nums[i] + 1, i + 1) - search(nums, lower - nums[i], i + 1);
27+
}
28+
return ans;
29+
}
30+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
'''
2+
Author: LetMeFly
3+
Date: 2025-04-19 16:13:37
4+
LastEditors: LetMeFly.xyz
5+
LastEditTime: 2025-04-19 16:23:38
6+
'''
7+
from typing import List
8+
from bisect import bisect_left, bisect_right
9+
10+
11+
class Solution:
12+
def countFairPairs(self, nums: List[int], lower: int, upper: int) -> int:
13+
nums.sort()
14+
return sum(bisect_right(nums, upper - nums[i], i + 1) - bisect_left(nums, lower - nums[i], i + 1) for i in range(len(nums)))

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -779,6 +779,7 @@
779779
|2558.从数量最多的堆取走礼物|简单|<a href="https://leetcode.cn/problems/take-gifts-from-the-richest-pile/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2023/10/28/LeetCode%202558.%E4%BB%8E%E6%95%B0%E9%87%8F%E6%9C%80%E5%A4%9A%E7%9A%84%E5%A0%86%E5%8F%96%E8%B5%B0%E7%A4%BC%E7%89%A9/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/134088006" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/take-gifts-from-the-richest-pile/solutions/2501756/letmefly-2558cong-shu-liang-zui-duo-de-d-amgs/" target="_blank">LeetCode题解</a>|
780780
|2559.统计范围内的元音字符串数|中等|<a href="https://leetcode.cn/problems/count-vowel-strings-in-ranges/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2023/06/02/LeetCode%202559.%E7%BB%9F%E8%AE%A1%E8%8C%83%E5%9B%B4%E5%86%85%E7%9A%84%E5%85%83%E9%9F%B3%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%95%B0/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/131014779" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/count-vowel-strings-in-ranges/solutions/2294361/letmefly-2559tong-ji-fan-wei-nei-de-yuan-mq4f/" target="_blank">LeetCode题解</a>|
781781
|2562.找出数组的串联值|简单|<a href="https://leetcode.cn/problems/find-the-array-concatenation-value/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2023/10/12/LeetCode%202562.%E6%89%BE%E5%87%BA%E6%95%B0%E7%BB%84%E7%9A%84%E4%B8%B2%E8%81%94%E5%80%BC/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/133797249" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/find-the-array-concatenation-value/solutions/2479676/letmefly-2562zhao-chu-shu-zu-de-chuan-li-5atk/" target="_blank">LeetCode题解</a>|
782+
|2563.统计公平数对的数目|中等|<a href="https://leetcode.cn/problems/count-the-number-of-fair-pairs/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2025/04/19/LeetCode%202563.%E7%BB%9F%E8%AE%A1%E5%85%AC%E5%B9%B3%E6%95%B0%E5%AF%B9%E7%9A%84%E6%95%B0%E7%9B%AE/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/147354620" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/count-the-number-of-fair-pairs/solutions/3656121/letmefly-2563tong-ji-gong-ping-shu-dui-d-u9bf/" target="_blank">LeetCode题解</a>|
782783
|2575.找出字符串的可整除数组|中等|<a href="https://leetcode.cn/problems/find-the-divisibility-array-of-a-string/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2024/03/07/LeetCode%202575.%E6%89%BE%E5%87%BA%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%9A%84%E5%8F%AF%E6%95%B4%E9%99%A4%E6%95%B0%E7%BB%84/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/136544808" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/find-the-divisibility-array-of-a-string/solutions/2673564/letmefly-2575zhao-chu-zi-fu-chuan-de-ke-rbnfy/" target="_blank">LeetCode题解</a>|
783784
|2576.求出最多标记下标|中等|<a href="https://leetcode.cn/problems/find-the-maximum-number-of-marked-indices/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2024/09/12/LeetCode%202576.%E6%B1%82%E5%87%BA%E6%9C%80%E5%A4%9A%E6%A0%87%E8%AE%B0%E4%B8%8B%E6%A0%87/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/142188013" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/find-the-maximum-number-of-marked-indices/solutions/2915060/letmefly-2576qiu-chu-zui-duo-biao-ji-xia-t2gd/" target="_blank">LeetCode题解</a>|
784785
|2578.最小和分割|简单|<a href="https://leetcode.cn/problems/split-with-minimum-sum/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2023/10/09/LeetCode%202578.%E6%9C%80%E5%B0%8F%E5%92%8C%E5%88%86%E5%89%B2/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/133694187" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/split-with-minimum-sum/solutions/2473429/letmefly-2578zui-xiao-he-fen-ge-tan-xin-pxbyl/" target="_blank">LeetCode题解</a>|
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
---
2+
title: 2563.统计公平数对的数目:排序 + 二分查找
3+
date: 2025-04-19 16:46:20
4+
tags: [题解, LeetCode, 中等, 数组, 双指针, 二分查找, 排序]
5+
categories: [题解, LeetCode]
6+
---
7+
8+
# 【LetMeFly】2563.统计公平数对的数目:排序 + 二分查找
9+
10+
力扣题目链接:[https://leetcode.cn/problems/count-the-number-of-fair-pairs/](https://leetcode.cn/problems/count-the-number-of-fair-pairs/)
11+
12+
<p>给你一个下标从 <strong>0</strong> 开始、长度为 <code>n</code> 的整数数组&nbsp;<code>nums</code>&nbsp;,和两个整数&nbsp;<code>lower</code> 和&nbsp;<code>upper</code> ,返回 <strong>公平数对的数目</strong> 。</p>
13+
14+
<p>如果&nbsp;<code>(i, j)</code>&nbsp;数对满足以下情况,则认为它是一个 <strong>公平数对</strong>&nbsp;:</p>
15+
16+
<ul>
17+
<li><code>0 &lt;= i &lt; j &lt; n</code>,且</li>
18+
<li><code>lower &lt;= nums[i] + nums[j] &lt;= upper</code></li>
19+
</ul>
20+
21+
<p>&nbsp;</p>
22+
23+
<p><b>示例 1:</b></p>
24+
25+
<pre>
26+
<b>输入:</b>nums = [0,1,7,4,4,5], lower = 3, upper = 6
27+
<b>输出:</b>6
28+
<b>解释:</b>共计 6 个公平数对:(0,3)、(0,4)、(0,5)、(1,3)、(1,4) 和 (1,5) 。
29+
</pre>
30+
31+
<p><b>示例 2:</b></p>
32+
33+
<pre>
34+
<b>输入:</b>nums = [1,7,9,2,5], lower = 11, upper = 11
35+
<b>输出:</b>1
36+
<b>解释:</b>只有单个公平数对:(2,3) 。
37+
</pre>
38+
39+
<p>&nbsp;</p>
40+
41+
<p><strong>提示:</strong></p>
42+
43+
<ul>
44+
<li><code>1 &lt;= nums.length &lt;= 10<sup>5</sup></code></li>
45+
<li><code>nums.length == n</code></li>
46+
<li><code>-10<sup>9</sup>&nbsp;&lt;= nums[i] &lt;= 10<sup>9</sup></code></li>
47+
<li><code>-10<sup>9</sup>&nbsp;&lt;= lower &lt;= upper &lt;= 10<sup>9</sup></code></li>
48+
</ul>
49+
50+
51+
52+
## 解题方法:排序 + 二分查找
53+
54+
要找的是值在一定范围内的$nums[i] + nums[j]$,且加法满足交换律($a+b=b+a$),所以查找结果和元素顺序无关。
55+
56+
所以只需要遍历$nums$的下标作为$i$,并在$i+1$到数组末尾的范围内查找$j$的范围,最终累加到答案中即可。
57+
58+
> 如何确定$j$的范围?$upper\_bound(upper - i) - lower\_bound(lower - i)$或$lower\_bound(upper - i + 1) - lower_bound(lower - i)$均可。
59+
>
60+
> 其中$lower_bound(t)$是非递减数组中第一个插入$t$后数组仍非递减的下标,$upper_bound(t)$是非递减数组中最后一个插入$t$后数组仍非递减的下标。
61+
62+
+ 时间复杂度$O(n\log n)$,其中$n=len(nums)$
63+
+ 空间复杂度$O(\log n)$
64+
65+
### AC代码
66+
67+
#### C++
68+
69+
```cpp
70+
/*
71+
* @Author: LetMeFly
72+
* @Date: 2025-04-19 15:51:42
73+
* @LastEditors: LetMeFly.xyz
74+
* @LastEditTime: 2025-04-19 16:12:44
75+
*/
76+
/*
77+
l: first j 满足 nums[j] + nums[i] >= lower | nums[j] >= lower - nums[i]
78+
r: last j 满足 nums[j] + nums[i] <= upper | nums[j] <= upper - nums[i]
79+
80+
l: lower_bound(lower - nums[i])
81+
r: upper_bound(upper - nums[i])
82+
*/
83+
typedef long long ll;
84+
class Solution {
85+
public:
86+
long long countFairPairs(vector<int>& nums, int lower, int upper) {
87+
sort(nums.begin(), nums.end());
88+
ll ans = 0;
89+
for (int i = 0; i < nums.size(); i++) {
90+
ans += upper_bound(nums.begin() + i + 1, nums.end(), upper - nums[i]) - lower_bound(nums.begin() + i + 1, nums.end(), lower - nums[i]);
91+
// 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;
92+
}
93+
return ans;
94+
}
95+
};
96+
```
97+
98+
#### Python
99+
100+
```python
101+
'''
102+
Author: LetMeFly
103+
Date: 2025-04-19 16:13:37
104+
LastEditors: LetMeFly.xyz
105+
LastEditTime: 2025-04-19 16:23:38
106+
'''
107+
from typing import List
108+
from bisect import bisect_left, bisect_right
109+
110+
111+
class Solution:
112+
def countFairPairs(self, nums: List[int], lower: int, upper: int) -> int:
113+
nums.sort()
114+
return sum(bisect_right(nums, upper - nums[i], i + 1) - bisect_left(nums, lower - nums[i], i + 1) for i in range(len(nums)))
115+
```
116+
117+
#### Java
118+
119+
```java
120+
/*
121+
* @Author: LetMeFly
122+
* @Date: 2025-04-19 16:24:08
123+
* @LastEditors: LetMeFly.xyz
124+
* @LastEditTime: 2025-04-19 16:37:36
125+
*/
126+
import java.util.Arrays;
127+
128+
class Solution {
129+
private int search(int[] nums, int x, int l) { // search [l, len(nums)) 范围内第一个大于等于x的下标
130+
int r = nums.length;
131+
while (l < r) {
132+
int mid = (l + r) >> 1;
133+
if (nums[mid] >= x) {
134+
r = mid;
135+
} else {
136+
l = mid + 1;
137+
}
138+
}
139+
return l;
140+
}
141+
public long countFairPairs(int[] nums, int lower, int upper) {
142+
Arrays.sort(nums);
143+
long ans = 0;
144+
for (int i = 0; i < nums.length; i++) {
145+
ans += search(nums, upper - nums[i] + 1, i + 1) - search(nums, lower - nums[i], i + 1);
146+
}
147+
return ans;
148+
}
149+
}
150+
```
151+
152+
#### Go
153+
154+
```go
155+
/*
156+
* @Author: LetMeFly
157+
* @Date: 2025-04-19 16:24:24
158+
* @LastEditors: LetMeFly.xyz
159+
* @LastEditTime: 2025-04-19 16:43:06
160+
*/
161+
package main
162+
import (
163+
"sort"
164+
)
165+
166+
func countFairPairs(nums []int, lower int, upper int) (ans int64) {
167+
sort.Ints(nums)
168+
for i, v := range nums {
169+
l := sort.Search(len(nums), func(x int) bool {return x > i && nums[x] >= lower - v})
170+
r := sort.Search(len(nums), func(x int) bool {return x > i && nums[x] >= upper - v + 1})
171+
ans += int64(r - l)
172+
}
173+
return
174+
}
175+
```
176+
177+
> 同步发文于[CSDN](https://letmefly.blog.csdn.net/article/details/147354620)和我的[个人博客](https://blog.letmefly.xyz/),原创不易,转载经作者同意后请附上[原文链接](https://blog.letmefly.xyz/2025/04/19/LeetCode%202563.%E7%BB%9F%E8%AE%A1%E5%85%AC%E5%B9%B3%E6%95%B0%E5%AF%B9%E7%9A%84%E6%95%B0%E7%9B%AE/)哦~
178+
>
179+
> 千篇源码题解[已开源](https://github.com/LetMeFly666/LeetCode)

0 commit comments

Comments
 (0)