SWE / Data Engineer · Coding

Meta 平均评分:聚合键、Sum/Count与合并

用累计和及计数计算平均评分,明确独立观察、重复投票和空组语义。

题目重点:用累计和及计数计算平均评分,明确独立观察、重复投票和空组语义。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • 训练输入(videoId,rating)独立观察,整数1..5,按video返回mean。实际题目只披露avg rating,分组键/更新规则未给,这里字段和范围是练习合同。
  • 不自动把同用户多票改成最新一票;若要求每用户当前评分,要提供userId/version并先去重。未出现video不输出0平均。

解题路线

  1. 每条更新totals[video]+=rating、counts[video]+=1,最后sum/count;分组键是题面明确对象,不能把全平台平均答作每视频平均。
  2. 重复调用/分批聚合需保存sum/count,不仅平均数。两组均值直接平均忽略样本量,要用(sum1+sum2)/(count1+count2)。
  3. 整数sum保持精确,最终除法才产生float;长期增量小数累加可有舍入误差,若要求精确有理数可输出Fraction或sum/count对。
  4. 无观察分母0,不能凭空给0当真实评分;输入非法评分拒绝,是否跳过坏行要另外定。用户更新评分时先撤旧值再加新值,计数不应再+1。

手动走一遍

A评分[1,5]均3,B[5]均5;合并全部三票平均11/3,不是(3+5)/2=4。空输入{},不存在视频不是0分。

Python 参考实现

下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。

代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。

def average_ratings(rows):
    """Training (video_id, integer rating 1..5) independent observations.
    No implicit replacement of a user's older vote; missing videos omitted.
    """
    totals={};counts={}
    for video,rating in rows:
        if not isinstance(rating,int) or not 1<=rating<=5:raise ValueError('1..5 ratings')
        totals[video]=totals.get(video,0)+rating;counts[video]=counts.get(video,0)+1
    return {video:totals[video]/counts[video] for video in totals}

复杂度

O(R)行处理/O(V)分组状态,输出O(V)。流式不保存所有rating,但distinct video数很大仍需分区/外聚合;float输出精度受结果表示限制。

易错点与追问

容易失分的边界

  • 直接均值的均值产生权重错误。
  • 最新评分合同缺userId却擅自去重。

继续深挖

  • 窗口评分到期如何减旧贡献并处理空组?
  • 如果输入包含权重,需保存加权sum和weightSum而非票数。
✓已复制微信号!