力扣 825. 适龄的朋友

题目说明

在社交媒体网站上有 n 个用户。给你一个整数数组 ages ,其中 ages[i] 是第 i 个用户的年龄。

如果下述任意一个条件为真,那么用户 x 将不会向用户 y(x != y)发送好友请求:

  • age[y] <= 0.5 * age[x] + 7
  • age[y] > age[x]
  • age[y] > 100 && age[x] < 100
    否则,x 将会向 y 发送一条好友请求。

注意,如果 x 向 y 发送一条好友请求,y 不必也向 x 发送一条好友请求。另外,用户不会向自己发送好友请求。

返回在该社交媒体网站上产生的好友请求总数。

提示:

  • n == ages.length
  • 1 <= n <= 2 * 10^4
  • 1 <= ages[i] <= 120

示例

示例 1:

1
2
3
输入:ages = [16,16]
输出:2
解释:2 人互发好友请求。

示例 2:

1
2
3
输入:ages = [16,17,18]
输出:2
解释:产生的好友请求为 17 -> 16 ,18 -> 17 。

示例 3:

1
2
3
输入:ages = [20,30,100,110,120]
输出:3
解释:产生的好友请求为 110 -> 100 ,120 -> 110 ,120 -> 100 。

笔者理解

此题是一道数组算法问题,在力扣题库中被定义为中等题。

解法

当笔者阅读完此题后,发现此题中我们可以先对数组进行排序,然后根据题目两个约束(虽然是三个条件,但实际符合前两个条件即可),用双指针来寻找符合条件的区间,让我们来看看具体如何实现的吧。

实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class Solution {
/**
* 数组
* 双指针
*/
public int numFriendRequests(int[] ages) {
int n = ages.length;
int result = 0;

Arrays.sort(ages);
int left = 0, right = 0;

// 此时 age 是 ages[x]
// 要寻找符合条件的 ages[y] 区间
// 因为随着 ages[x] 的变大,ages[y] 左右区间也是向后偏移的,
for (int age : ages) {


// 当 ages[x] < 15 时,找不到符合条件的 ages[y]
if (age < 15) {
continue;
}

// 配对的左区间
while (ages[left] <= 0.5 * age + 7) {
left++;
}

// 配对的右区间
while (right < n - 1 && ages[right + 1] <= age) {
right++;
}

// 累加这个区间
result += right - left;
}

return result;
}
}

时间和空间效率还行,可见此解法还比较适合此题。

image-20211227233415373

总结

本题是今天的每日一题,难度是为中等,感兴趣的朋友都可以去尝试一下,此题还有其他更多的解法,朋友们可以自己逐一尝试。