825. Friends Of Appropriate Ages**

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 request B.

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.

前言

有个笑话, 我必须笑一下:

因为我在写代码的过程中也发现了这个问题, 然后停下来开始怀疑了人生 … 🤣🤣🤣

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] + 7upper_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;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值