Member / SWE · Technical Problem Solving / VO

Netflix 首页 Shelf 去重:前 X 个显示位跨行,后续只在行内

结合两篇 Netflix 面经澄清首页多行标题去重的作用域、跳过标题后的补位语义与每行不同 X 追问,给出线性扫描实现。

题目重点:结合两篇 Netflix 面经澄清首页多行标题去重的作用域、跳过标题后的补位语义与每行不同 X 追问,给出线性扫描实现。

题意与假设

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

  • 训练代码把 X 解释为每行前 X 个实际输出位置;跳过重复候选后继续扫描以补足这些位置。题目写 viewport 最多显示 X 个,但未明确被跳过候选是否补位,因此需面试时确认。
  • 同一行所有输出都行内唯一。前 X 个输出位置还要与之前所有行的前 X 个已展示标题不同;后续位置允许与此前行重复。
  • 输入按行顺序与各行原顺序扫描;title 可哈希。垂直可视范围视为无限;X 非负。

解题路线

  1. 维护 global_visible,存此前占据各行前 X 个输出位的 title。每行新建 local,存本行已输出 title。
  2. 扫描候选时先排除本行已输出者。若当前输出数仍小于 X,再排除 global_visible 中的 title;接纳后同时写 global_visible 与 local。若已满 X,只检查 local。
  3. 的每行不同 X 追问只需把本行阈值改为 X_i;特殊行是否向 global_visible 贡献标题与是否仍受前行限制,是两条独立规则,应先澄清再改代码。

手动走一遍

训练例 shelves=[[1,2,2,3],[2,4,1,5]], X=2。首行输出 [1,2,3];第二行前两位跳过 2、1,收下 4、5,输出 [4,5]。若第二行后面又出现 2,已越过前两位,可输出 2;但再次出现 4 会被行内集合拦下。

Python 参考实现

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

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

def dedupe_shelves(shelves, viewport_size):
    """Global uniqueness applies only to each shelf's first viewport_size outputs."""
    if viewport_size < 0:
        raise ValueError("viewport_size must be nonnegative")
    global_visible = set()
    result = []
    for shelf in shelves:
        output = []
        local = set()
        for title in shelf:
            if title in local:
                continue
            if len(output) < viewport_size:
                if title in global_visible:
                    continue
                global_visible.add(title)
            output.append(title)
            local.add(title)
        result.append(output)
    return result

复杂度

总候选标题数 N,预期哈希时间 O(N);空间 O(G+L+O),G 为跨行前 X 个标题的不同数、L 为当前行已输出标题数、O 为结果大小。若不保留全部输出,只流式生成行,额外空间可降至 O(G+L)。

易错点与追问

容易失分的边界

  • 整行跨行去重,会错误删除 X 之后允许出现的标题。
  • 只用一个全局 set,不维护 local,导致行内重复重新出现。
  • 把全局 set 的长度当成当前行的位置;前面所有行都会污染阈值。
  • 被跳过候选是否占 viewport 位未确认就下结论。
  • 把一个帖中候选人多次修改的版本当成多道独立原题。

继续深挖

  • 每行 X_i 不同,是否共享一个跨行全局集合?
  • 某些特殊行豁免跨行去重时,是否仍占后续行的全局名额?
  • 若按实际水平滚动 viewport 去重,已离开视口的标题何时可重新展示?
✓已复制微信号!