2021.12.27 力扣-每日一题-适龄的朋友

这篇博客探讨了一种解决社交媒体网站上好友请求问题的算法。方法一是通过预处理年龄分布,利用前缀和技巧计算好友请求总数;方法二是直接遍历年龄数组,用判断函数检查每个用户能否发送好友请求。这两种方法都有效地处理了年龄限制和条件判断,避免了无效的请求。
摘要由CSDN通过智能技术生成

目录

题目描述:

样例:

方法一:

方法二


题目描述:

在社交媒体网站上有 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 发送一条好友请求。另外,用户不会向自己发送好友请求。

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

样例:

方法一:

class Solution {
public:
    int numFriendRequests(vector<int>& ages) {
        int cnt[121] = {0};     //cnt[i]表示年龄为i的人数
        for (int i = 0; i < ages.size(); i++)
        {
            cnt[ages[i]]++;
        }
        int pre[121] = {0};     //pre[i]表示年龄小于等于i的人数
        for (int i = 1; i <= 120; i++)
        {
            pre[i] = pre[i - 1] + cnt[i];
        }
        int ans = 0;
        for (int i = 15; i <= 120; i++)
        {
            if (cnt[i])
            {
                int minage = 0.5 * i + 7;
                //对于每个年龄为i的人,他会向pre[i] - pre[minage] - 1个人发送好友请求,其中包括年龄等于他的人,减一是要排除自己
                ans += cnt[i] * (pre[i] - pre[minage] - 1);
            }
        }
        return ans;
    }
};

看完多个题解后,发现还是这种方法最方便,由于年龄只限定在1到120之间,所以可以直接开两个数组,一个cnt[i]用于记录年龄为i的人数,一个pre[i]用于记录年龄小于等于i的人数。

由题目可知,对于每个年龄为age的人来说,其能够向以下年龄范围内的人发送好友请求:

                                                ( 0.5 * age + 7, age】

所以即是pre[i] - pre[minage] - 1,减一是因为自己不能够向自己发送好友请求。

另外当0.5 * age + 7 >= age,即age <= 14 时,此区间将不存在,即年龄小于等于14的人不能发送任何的好友请求,所以不必考虑年龄小于等于14的人。

方法二

class Solution {
public:
    //利用题目所给的三个条件,判断x是否能够向y发送好友请求
    bool judge(int agex, int agey)
    {
        if (agey <= 0.5 * agex + 7) return false;
        if (agey > agex) return false;
        if (agey > 100 && agex < 100) return false;
        return true;
    }
    int numFriendRequests(vector<int>& ages) {
        //sumages[i]表示年龄为i的人数
        vector<int> sumages(121, 0);
        for (int age : ages) sumages[age]++;
        int ans = 0;
        //根据条件2可知,用户只有可能向年龄小于等于自己的人发送好友请求,因此年龄从大往小遍历
        for (int agex = 120; agex > 0; agex--)
        {
            if (!sumages[agex]) continue;       //如果年龄为agex的人不存在,跳过
            for (int agey = agex; agey > 0; agey--)
            {
                if (!sumages[agey]) continue;   //如果年龄为agey的人不存在,跳过
                //如果agex和agey满足条件,就发送好友请求
                if (judge(agex, agey))
                {
                    //当agex == agey时,将会产生sumages[agex] * (sumages[agex] - 1)条好友请求(排列数A(2,2))
                    //当agex != agey时,将会产生sumages[agex] * sumages[agey]条好友请求
                    ans += agex == agey ? sumages[agex] * (sumages[agex] - 1) : sumages[agex] * sumages[agey];
                }
            }
        }
        return ans;
    }
};

以前写过的那种前缀和的方法,在边界上实在令人头疼,真不想再看一遍了,一年过后自己写了这种比较简单的方法,时间复杂度不超过10^4

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值