SWE / Data Platform · VO Coding

Netflix 最后 K 部电影:相同集合分组与至少 M 重叠配对

按用户最近 K 条观看历史形成集合,分组同集合用户,再找电影交集至少 M 的用户对,区分顺序、重复电影与候选剪枝。

题目重点:按用户最近 K 条观看历史形成集合,分组同集合用户,再找电影交集至少 M 的用户对,区分顺序、重复电影与候选剪枝。

题意与假设

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

  • 历史按观看先后排列,取最后 K 条记录后转集合;同一电影在最后 K 条内重复只计一个电影。题目写最后 K 部电影,若指 K 个不同片名需另定。
  • 历史不足 K 条的用户在训练版不参与比较;K=0 时所有用户都是空集合。用户 id 可排序以稳定输出。
  • 按集合交集大小≥M 判断 pair;M=0 返回所有合格用户对。题目未明确是否只返回最大连通群,本文按 pair 字面要求。

解题路线

  1. 先对每名用户切取最后 K 条,转 frozenset 作为稳定哈希键。相同集合分组可用 `map[frozenset]→users`,只输出人数至少 2 的组。
  2. 追问从两两用户对的集合交集基线出发;因为‘重叠至少 M’不具传递性,不能把边连成连通分量后当作同组。
  3. 若用户数 U 很大,给每部电影建倒排索引,仅枚举共享电影的候选用户对并累积交集计数;M=0 仍可能有 Θ(U²) 输出,因此没有普遍次二次最坏时间。热点电影需要压缩 posting、分片或分层过滤。

手动走一遍

训练例 A 最近两条 [X,Y]、B [Y,X]、C [X,Z]。A/B 属于同集合组;M=1 时 A-B、A-C、B-C 都是合格 pair;M=2 时只有 A-B。若 A 最近两条是 [X,X],其集合大小为 1,不等于 [X,Y]。

Python 参考实现

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

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

from collections import defaultdict
from itertools import combinations


def group_same_last_k(histories, k):
    if k < 0:
        raise ValueError("k must be nonnegative")
    groups = defaultdict(list)
    for user, movies in histories.items():
        if len(movies) < k:
            continue
        key = frozenset(movies[-k:] if k else ())
        groups[key].append(user)
    return [sorted(users) for users in groups.values() if len(users) > 1]


def pairs_with_at_least_m_overlap(histories, k, m):
    if k < 0 or m < 0:
        raise ValueError("k and m must be nonnegative")
    users = sorted(user for user, movies in histories.items() if len(movies) >= k)
    recent = {user: set(histories[user][-k:] if k else ()) for user in users}
    return [(left, right) for left, right in combinations(users, 2)
            if len(recent[left] & recent[right]) >= m]

复杂度

取历史尾部与构建集合总计 O(UK);同集合分组预期 O(UK) 时间和空间。两两 pair 基线 O(U²K) 时间、O(UK+P) 空间,P 为输出 pair 数;倒排候选可在稀疏数据上更快,但热门电影仍可能产生二次候选。

易错点与追问

容易失分的边界

  • 把最近 K 条按顺序 tuple 比较,违背‘集合相同’。
  • 先对全部历史去重再取 K,改变最后 K 的语义。
  • 把 M 重叠关系当等价关系做并查集,错误扩大分组。
  • 忘记同一电影在近期重复时集合大小会小于 K。
  • 未考虑输出本身可能有 O(U²) 对。

继续深挖

  • 如果要求最近 K 个不同片名,要怎样从尾部扫描?
  • 数据流新增观看事件时如何增量更新分组键?
  • 热门电影造成倒排组合爆炸时如何先做稀疏过滤或分布式聚合?
✓已复制微信号!