题目重点:用累计和及计数计算平均评分,明确独立观察、重复投票和空组语义。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 训练输入(videoId,rating)独立观察,整数1..5,按video返回mean。实际题目只披露avg rating,分组键/更新规则未给,这里字段和范围是练习合同。
- 不自动把同用户多票改成最新一票;若要求每用户当前评分,要提供userId/version并先去重。未出现video不输出0平均。
解题路线
- 每条更新totals[video]+=rating、counts[video]+=1,最后sum/count;分组键是题面明确对象,不能把全平台平均答作每视频平均。
- 重复调用/分批聚合需保存sum/count,不仅平均数。两组均值直接平均忽略样本量,要用(sum1+sum2)/(count1+count2)。
- 整数sum保持精确,最终除法才产生float;长期增量小数累加可有舍入误差,若要求精确有理数可输出Fraction或sum/count对。
- 无观察分母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而非票数。
