825. Friends Of Appropriate Ages**
https://leetcode.com/problems/friends-of-appropriate-ages/
题目描述
Some people will make friend requests. The list of their ages is given and ages[i]
is the age of the ith
person.
Person A
will NOT friend request person B
(B
!= A
) if any of the following conditions are true:
age[B] <= 0.5 * age[A] + 7
age[B] > age[A]
age[B] > 100 && age[A] < 100
Otherwise,A
will friend requestB
.
Note that if A
requests B
, B
does not necessarily request A
. Also, people will not friend request themselves.
How many total friend requests are made?
Example 1:
Input: [16,16]
Output: 2
Explanation: 2 people friend request each other.
Example 2:
Input: [16,17,18]
Output: 2
Explanation: Friend requests are made 17 -> 16, 18 -> 17.
Example 3:
Input: [20,30,100,110,120]
Output:
Explanation: Friend requests are made 110 -> 100, 120 -> 110, 120 -> 100.
Notes:
1 <= ages.length <= 20000
.1 <= ages[i] <= 120
.
前言
有个笑话, 我必须笑一下:
![](https://i-blog.csdnimg.cn/blog_migrate/1a0abfd2d6a77a27b18a77b2ec9bc82e.png)
因为我在写代码的过程中也发现了这个问题, 然后停下来开始怀疑了人生 … 🤣🤣🤣
C++ 实现 1
我的思路稍微复杂一些, 要简洁的方法可以看 C++ 实现 2
.
从第二个条件可以发现, 年轻的不会和年老的交友, 因此对年龄从小到大排序, 从后向前开始考虑. 对于 ages[i]
, 它只能和 [0 ... i - 1]
范围内的人交友. 但这里有个例外, 即 ages[i] == ages[i - 1]
时, 此时 ages[i - 1]
也能和 ages[i]
交友, 这种特殊情形我们之后考虑.
由于 ages[i]
不会和 age[B] <= 0.5 * age[i] + 7
的人交朋友, 其实就是在数组找 0.5 * age[i] + 7
的 upper_bound
, 即第一个大于 0.5 * age[i] + 7
的数 (更具体是 int(std::floor(ages[i] / 2.)) + 7
, 代入一个具体的数值进去就会发现是 floor
而不是 ceil
.). 第三个条件 age[B] > 100 && age[A] < 100
是冗余的, 包含于条件二, 因此不用考虑. 那么 ages[i]
能交友的范围为 [j, i - 1]
, 个数就是 (i - 1) + 1 - j = i - j
个. 然而这里有两个问题:
- 如果
j
不存在, 即upper_bound
不存在, 那么j = ages.size()
,i - j
此时小于 0, 因此最后用std::max(i - j, 0)
表示ages[i]
能交友的个数. - 另外还需要考虑
ages[i] == ages[i + 1]
的情况, 此时ages[i]
的交友个数其实和ages[i + 1]
的交友个数一样, 因此用prev
表示ages[i + 1]
的交友个数; 当访问到ages[i]
时, 如果ages[i] == ages[i+ 1]
, 那么交友个数就是prev
.
class Solution {
public:
int numFriendRequests(vector<int>& ages) {
std::sort(ages.begin(), ages.end());
int res = 0, prev = 0;
for (int i = ages.size() - 1; i >= 0; -- i) {
int target = int(std::floor(ages[i] / 2.)) + 7;
int j = std::upper_bound(ages.begin(), ages.end(), target) - ages.begin();
if (i < ages.size() - 1 && ages[i] == ages[i + 1]) res += prev;
else {
res += std::max(i - j, 0);
prev = std::max(i - j, 0);
}
}
return res;
}
};
C++ 实现 2
来自 LeetCode Submission. 由于年龄的大小是有限制的, 在 0 ~ 120
之间, 因此可以用数组保存各个年龄的人数, 然后过滤不满足条件的交友关系, 另外注意不能和自己交友.
class Solution {
public:
int numFriendRequests(vector<int>& ages) {
vector<int> count(121, 0);
int ret = 0;
for (int age : ages) count[age]++;
for (int i = 0; i < 121; i++) {
for (int j = 0; j < 121; j++) {
if (j <= 0.5 * i + 7) continue;
if (j > i) continue;
if (j > 100 && i < 100) continue;
ret += count[i] * count[j];
if (i == j) ret -= count[i]; // 不能和自己交友
}
}
return ret;
}
};