首页 > 其他分享 >力扣825.适龄的朋友,全网最详细解释

力扣825.适龄的朋友,全网最详细解释

时间:2024-11-17 13:15:51浏览次数:3  
标签:适龄 cnt 16 ageX ages 用户 力扣 825 年龄

好友请求的总数(LeetCode 825)

题目描述

某社交平台规定,用户 A 可以向用户 B 发送好友请求需满足以下条件:

  1. 用户 A 的年龄不小于用户 B 的年龄。
  2. 用户 B 的年龄大于 0.5 * 用户 A 的年龄 + 7
  3. 用户 B 的年龄小于等于用户 A 的年龄。

此外,一个用户不能向自己发送好友请求。

输入
一个整数数组 ages,表示每个用户的年龄。

输出
一个整数,表示好友请求的总数。


示例

示例 1

输入

ages = [16, 16]

输出

2

解释

  • 两个用户均为 16 岁,他们可以互相发送好友请求。

示例 2

输入

ages = [16, 17, 18]

输出

2

解释

  • 用户 16 岁向 16 岁和 17 岁发送好友请求。
  • 用户 17 岁只能向 16 岁发送好友请求。
  • 用户 18 岁可以向 17 岁发送好友请求。

解题思路

分析条件

根据题目中的条件,我们需要逐步分析满足好友请求的条件:

  1. 用户 A 的年龄不小于用户 B 的年龄(ages[A] >= ages[B])。
  2. 用户 B 的年龄满足 ages[B] > 0.5 * ages[A] + 7
  3. 用户 B 的年龄小于等于用户 A 的年龄(此条件已隐含在条件 1 中)。

优化思路

1. 计数统计

由于用户的年龄范围限制为 1 至 120,我们可以用一个数组 cnt 来统计每个年龄的出现次数。这样,可以避免对每对用户进行暴力比较。

2. 滑动窗口

当我们枚举用户 A 的年龄 ageX 时,需要知道哪些年龄的用户可以成为好友请求的接收者:

  • 最小年龄 ageY = 0.5 * ageX + 7
  • 接收者的年龄范围 [ageY, ageX]

因为 ageX 递增时,ageY 也递增,因此可以通过滑动窗口方法高效统计区间内的用户数。

3. 好友请求数计算

对于每个年龄 ageX

  1. 如果该年龄的人数为 cnt[ageX],区间内人数为 cnt_window
    • 该年龄的用户可以向 cnt_window 人发送好友请求。
    • 由于一个用户不能向自己发送请求,因此需要减去 cnt[ageX]
  2. 更新总的好友请求数为:
    cnt[ageX] * cnt_window - cnt[ageX]
    

实现代码

Python 解法

from typing import List

class Solution:
    def numFriendRequests(self, ages: List[int]) -> int:
        # 统计每个年龄的用户数量
        cnt = [0] * 121
        for age in ages:
            cnt[age] += 1

        ans = 0  # 总好友请求数
        cnt_window = 0  # 当前窗口内的用户总数
        age_y = 0  # 最小年龄下界

        for age_x, c in enumerate(cnt):  # 遍历每个年龄
            cnt_window += c  # 当前年龄加入窗口
            while age_y * 2 <= age_x + 14:  # 不满足好友请求条件
                cnt_window -= cnt[age_y]
                age_y += 1
            if cnt_window > 0:  # 存在可以发送好友请求的用户
                ans += c * cnt_window - c
        return ans

复杂度分析

时间复杂度

  1. 遍历 ages 数组构造计数数组 cntO(n)
  2. 遍历所有可能的年龄范围 [0, 120]O(U),其中 U = 121 是年龄的最大值。
  3. 滑动窗口中每个年龄至多移动一次:总复杂度为 O(U)

综合时间复杂度为 O(n + U)

空间复杂度

  1. 使用了一个大小为 121 的计数数组 cntO(U)

综合空间复杂度为 O(U)


示例解析

示例 1

输入

ages = [16, 16]

执行过程

  1. 构造计数数组:cnt = [0, 0, ..., 2, ..., 0](索引 16 对应值为 2)。
  2. 滑动窗口遍历:
    • ageX = 16:窗口内包含用户 {16},满足条件人数为 2 - 1 = 1
  3. 总好友请求数:2 * 1 = 2

输出

2

示例 2

输入

ages = [16, 17, 18]

执行过程

  1. 构造计数数组:cnt = [0, ..., 1, 1, 1, ..., 0](索引 16、17、18 对应值为 1)。
  2. 滑动窗口遍历:
    • ageX = 16:窗口内包含用户 {16},无其他满足条件用户。
    • ageX = 17:窗口内包含用户 {16, 17},满足条件人数为 1
    • ageX = 18:窗口内包含用户 {16, 17, 18},满足条件人数为 2
  3. 总好友请求数:0 + 1 + 1 = 2

输出

2

扩展思考题

修改条件为
0.5 * ages[A] + 7 < ages[B] ≤ 2 * ages[A]
要满足新的条件:

  • 接收者的最大年龄需为 2 * ages[A]
  • 滑动窗口调整为 [ageY, 2 * ageX]
  • ageX 增加时,滑动窗口右边界也需动态调整。

代码略作修改即可完成。


总结

本题的关键在于:

  1. 利用计数数组减少冗余计算,避免暴力枚举用户对的复杂度。
  2. 滑动窗口的巧妙应用,高效统计年龄区间内的人数。
  3. 数学分析确保满足好友请求条件,结合乘法原理计算请求总数。

标签:适龄,cnt,16,ageX,ages,用户,力扣,825,年龄
From: https://blog.csdn.net/qq_17405059/article/details/143831149

相关文章

  • 力扣.223 矩形面积 rectangle-area
    题目给你二维平面上两个由直线构成且边与坐标轴平行/垂直的矩形,请你计算并返回两个矩形覆盖的总面积。每个矩形由其左下顶点和右上顶点坐标表示:第一个矩形由其左下顶点(ax1,ay1)和右上顶点(ax2,ay2)定义。第二个矩形由其左下顶点(bx1,by1)和右上顶点(bx2,b......
  • 力扣 LeetCode 94. 二叉树的中序遍历(Day6:二叉树)
    解题思路:方法一:递归(左中右)classSolution{List<Integer>res=newArrayList<>();publicList<Integer>inorderTraversal(TreeNoderoot){recur(root);returnres;}publicvoidrecur(TreeNoderoot){if(......
  • leetcode 扫描线专题 06-leetcode.252 meeting room 力扣.252 会议室
    扫描线专题leetcode扫描线专题06-扫描线算法(SweepLineAlgorithm)leetcode扫描线专题06-leetcode.218the-skyline-problem力扣.218天际线问题leetcode扫描线专题06-leetcode.252meetingroom力扣.252会议室leetcode扫描线专题06-leetcode.253meetingroomii......
  • 力扣-Mysql-3293-计算产品最终价格(中等)
    一、题目来源3293.计算产品最终价格-力扣(LeetCode)二、数据表结构表:Products+------------+---------+|ColumnName|Type|+------------+---------+|product_id|int||category|varchar||price|decimal|+------------+-------......
  • 力扣-Mysql-3308- 寻找表现最佳的司机(中等)
    一、题目来源3308.寻找表现最佳的司机-力扣(LeetCode)二、数据表结构表:Drivers+--------------+---------+|ColumnName|Type|+--------------+---------+|driver_id|int||name|varchar||age|int||experience......
  • 力扣-Mysql-3252-英超积分榜排名 II(中等)
    一、题目来源3252.英超积分榜排名II-力扣(LeetCode)二、数据表结构表:TeamStats+------------------+---------+|ColumnName|Type|+------------------+---------+|team_id|int||team_name|varchar||matches_played......
  • 力扣.1 两数之和 N 种解法 two-sum
    数组系列力扣数据结构之数组-00-概览力扣.53最大子数组和maximum-subarray力扣.128最长连续序列longest-consecutive-sequence力扣.1两数之和N种解法two-sum力扣.167两数之和IItwo-sum-ii力扣.170两数之和IIItwo-sum-iii力扣.653两数之和IVtwo-sum-......
  • 力扣—543.二叉树的直径
    543.二叉树的直径给你一棵二叉树的根节点,返回该树的 直径 。二叉树的 直径 是指树中任意两个节点之间最长路径的 长度 。这条路径可能经过也可能不经过根节点 root 。两节点之间路径的 长度 由它们之间边数表示。示例1:输入:root=[1,2,3,4,5]输出:3解释:3,取......
  • 2024.11.13 1825版
    起于《海奥华预言》的思考◆地球管理结构和参考持续更新中...... 英文地址:https://github.com/zhuyongzhe/Earth/tags中文地址:https://www.cnblogs.com/zhuyongzhe85作者:朱永哲 ---------------------------------------------------------------------------------......
  • 力扣刷题——3261. 统计满足 K 约束的子字符串数量 II
    看了题目的两个初始用例,感觉能用前缀和和滑动窗口来解决,前缀和设定为从下标0到当前位置所有符合条件的答案数量,于是先写了一个:vector<longlong>countKConstraintSubstrings(strings,intk,vector<vector<int>>&queries){intn=s.size();vector<longlong>pre......