leetcode825. 适龄的朋友

825. 适龄的朋友

提示:
n == ages.length
1 <= n <= 2 * 104
1 <= ages[i] <= 120

方法一:暴力遍历,n^2时间复杂度
js

var numFriendRequests = function(ages) {
    let cnt = 0;
    // 将ages按从大到小排序,这样遍历的时候就满足了ages[y] <= ages[x]这个条件
    ages.sort((a,b)=>b-a);
    for (let x = 0; x < ages.length; x++) {
        for (let y = x+1; y < ages.length; y++) {
        	// 在满足所有条件的情况下,如果年龄相等,可以相互发
            if (ages[y] > 0.5 * ages[x] + 7 && !(ages[y] > 100 && ages[x] < 100)) cnt = ages[x] === ages[y] ? cnt+2 : cnt+1
        }
    }
    return cnt;
};

方法二:排序+双指针
题目给出的3个条件为:

  1. ages[y] ≤ 0.5 × ages[x] + 7

  2. ages[y] > ages[x]

  3. ages[y] > 100 && ages[x] < 100

其中条件2包含条件3,所以如果条件2不满足的话,那条件3也不满足。
综上,只要不满足条件1和2,x 就可以给 y 发好友请求,即 0.5×ages[x]+7<ages[y]≤ages[x]

基于以上思路,将ages数组排序,对于ages中的每个age,用两个指针 left 和 right 来维护满足条件的
ages[y] 范围,并求和得出答案

js

	const n = ages.length;
    ages.sort((a, b) => a - b);
    let left = 0, right = 0, ans = 0;
    for (const age of ages) {
        // x的age<15一定不满足条件
        if (age < 15) continue;
        while (ages[left] <= 0.5 * age + 7) left++;
        while (right + 1 < n && ages[right + 1] <= age) ++right;
        // 这里要去掉x本身
        ans += right - left;
    }
    return ans;

方法三:计数排序 + 前缀和
和方法二类似思路,只不过排序方式改成计数排序,这样可以进一步降低时间复杂度到O(n)
相应地,统计总和的方式发生变化,采用了前缀和的方法
js

	const cnt = new Array(121).fill(0), pre = new Array(121).fill(0);
    let ans = 0;
    for (const age of ages) ++cnt[age];
    for (let i = 1; i <= 120; ++i) pre[i] = pre[i - 1] + cnt[i];
    for (let i = 15; i <= 120; ++i) {
        if (cnt[i] > 0) ans += cnt[i] * (pre[i] - pre[Math.floor(i * 0.5 + 7)] - 1);
    }
    return ans;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值