目标
在社交媒体网站上有 n 个用户。给你一个整数数组 ages ,其中 ages[i] 是第 i 个用户的年龄。
如果下述任意一个条件为真,那么用户 x 将不会向用户 y(x != y)发送好友请求:
- ages[y] <= 0.5 * ages[x] + 7
- ages[y] > ages[x]
- ages[y] > 100 && ages[x] < 100
否则,x 将会向 y 发送一条好友请求。
注意,如果 x 向 y 发送一条好友请求,y 不必也向 x 发送一条好友请求。另外,用户不会向自己发送好友请求。
返回在该社交媒体网站上产生的好友请求总数。
示例 1:
输入:ages = [16,16]
输出:2
解释:2 人互发好友请求。
示例 2:
输入:ages = [16,17,18]
输出:2
解释:产生的好友请求为 17 -> 16 ,18 -> 17 。
示例 3:
输入:ages = [20,30,100,110,120]
输出:3
解释:产生的好友请求为 110 -> 100 ,120 -> 110 ,120 -> 100 。
说明:
- n == ages.length
- 1 <= n <= 2 * 10^4
- 1 <= ages[i] <= 120
思路
某社交网站上有 n 个用户,ages[i]
表示用户 i
的年龄,当满足条件 ages[x] >= ages[y] && ages[y] > ages[x] / 2 + 7
时,用户 x
会向 y
发送好友申请。求网站上好友申请的总数。
第三个条件 ages[y] > 100 && ages[x] < 100
即 ages[y] > 100 > ages[x]
与第二个条件重复了,可以不考虑。
ages[x] >= ages[y] > ages[x] / 2 + 7
可以推出 ages[x] > 14
才可以发出好友申请,并且好友申请的对象也要满足 ages[y] > ages[x] / 2 + 7 > 14
,
将年龄从大到小排序后,使用滑动窗口计算即可。
瓶颈在于排序,可以使用计数排序。
代码
/**
* @date 2024-11-17 14:46
*/
public class NumFriendRequests825 {
public int numFriendRequests_v1(int[] ages) {
int n = ages.length;
int[] ageCnt = new int[121];
for (int i = 0; i < n; i++) {
ageCnt[ages[i]]++;
}
int res = 0, windowCnt = 0;
int l = 15;
for (int i = 15; i < 121; i++) {
windowCnt += ageCnt[i];
if (l * 2 - 14 <= i) {
windowCnt -= ageCnt[l++];
}
if (windowCnt > 0) {
res += ageCnt[i] * (windowCnt - 1);
}
}
return res;
}
public int numFriendRequests(int[] ages) {
Arrays.sort(ages);
int n = ages.length;
int r = n - 1, lowerBounds = ages[r] / 2 + 7;
int res = 0;
for (int l = n - 1; l >= 0 && ages[l] > 14; l--) {
while (ages[l] <= lowerBounds) {
lowerBounds = ages[--r] / 2 + 7;
}
res += r - l;
int e = l;
while (e < n - 1 && ages[e] == ages[e + 1]) {
res++;
e++;
}
}
return res;
}
}