目录
正在加载目录...

Netflix OA + 电面面经|CodeSignal 新题 + 首页去重设计全流程拆解

投的是 Netflix 的 Member, Commerce & Games Engineering 组。奈飞的面试在大厂里风格挺独特的——题目不算最难,但对 communication 和 clarification 的要求高得离谱,面试官给的需求全是 high level 的,input、output、每一条需求都得你自己问出来。趁记忆新鲜把 OA 和店面都记下来。

Netflix OA + 电面面经|CodeSignal 新题 + 首页去重设计全流程拆解

投的是 Netflix 的 Member, Commerce & Games Engineering 组。奈飞的面试在大厂里风格挺独特的——题目不算最难,但对 communication 和 clarification 的要求高得离谱,面试官给的需求全是 high level 的,input、output、每一条需求都得你自己问出来。趁记忆新鲜把 OA 和店面都记下来。

Netflix OA :CodeSignal 平台,三道题

奈飞的 OA 走 CodeSignal,题目都是近期的新题,一道概率 quiz 加两道 coding。

Quiz:条件概率送分题

题目给了个万圣节场景:三个朋友拿到红、蓝、绿三种包装的糖果,给出每人每种颜色的数量表——Jack Silver(红 5、蓝 10、绿 2),Blake Smith(红 20、蓝 4、绿 4),Carrie Silver(红 12、蓝 6、绿 2)。问:如果你姓 Silver,拿到蓝色包装糖果的概率是多少?

这题就是考你会不会读题。姓 Silver 的是 Jack 和 Carrie 两个人,把他们的糖果合起来算:总数 5+10+2+12+6+2 = 37,其中蓝色 10+6 = 16,答案 16/37。别把 Blake 的数据算进去就行。

Coding 1:Bucket 文件系统模拟

题意:你在一个虚拟环境里,只有两种命令——goto <bucket_name> 切换到指定 bucket(保证 bucket 存在),create <filename> 在当前 bucket 里创建文件(同名文件已存在则什么都不发生)。处理完所有命令后,返回文件数最多的 bucket 名(保证无并列)。

比如依次执行 goto bucketA、create fileA、create fileB、create fileA、goto bucketB、goto bucketC、create fileA、create fileB、create fileC,最后 bucketA 有两个文件(第二次 create fileA 无效),bucketB 空的,bucketC 三个,答案 bucketC。

思路就是字典套集合的纯模拟:

def solution(commands):
    buckets = {}
    current = None
    for cmd in commands:
        action, name = cmd.split()
        if action == "goto":
            current = name
            buckets.setdefault(current, set())
        else:  # create
            buckets[current].add(name)
    return max(buckets, key=lambda b: len(buckets[b]))

有个隐藏坑:题目第二个例子里 bucket 名和文件名是会撞的(bucket 叫 bar,文件也叫 bar),用集合按 bucket 隔离存就天然没问题。命令数最多 1000,随便过。

Coding 2:Cyclic Pairs

题意:cyclic shift 是把一个数末尾的若干位挪到开头,比如 546 的 cyclic shift 有 546、654、465。给一个正整数数组,统计有多少对 (i, j)(i<j),满足两数位数相同且 a[i] 是 a[j] 的某个 cyclic shift。

例子:a = [13, 5604, 31, 2, 13, 4560, 546, 654, 456],答案 5——13 和 31、13 和 13、31 和 13、5604 和 4560、546 和 654 都是合法对。注意 546 和 456 不是(456 不在 546 的 shift 集合里……等等,465 才是它的 shift,456 不是),4560 和 456 也不是因为位数不同。

数据规模 10⁵,两两比较 O(n²) 会挂,正确姿势是规范化 + 哈希计数:把每个数的所有 cyclic shift 算出来,取字典序最小的那个作为这个数的”标准形”,标准形相同的数互为 cyclic pair。然后统计每种标准形的出现次数 c,累加 c×(c-1)/2。

from collections import Counter

def solution(a):
    def canonical(x):
        s = str(x)
        # 注意前导零:shift 后带前导零的形态也算合法形态之一,
        # 用字符串旋转统一处理
        return min(s[i:] + s[:i] for i in range(len(s)))
    
    cnt = Counter(canonical(x) for x in a)
    return sum(c * (c - 1) // 2 for c in cnt.values())

每个数最多 10 位,规范化是 O(位数²),总复杂度约 O(n × 100),轻松过。这题的精髓就是”把等价类问题转成规范形计数”,想到这层代码就几行。

店面:两轮,全程围着 dedup 转

第一轮:解决问题轮

题目是设计 Netflix 首页的去重——首页可以横向滑动也可以竖向滑动,同一部剧不能重复出现。

面试官只给了非常 high level 的要求,input 格式、output 格式、每一条需求全要自己 clarify。我大概花了 15 分钟纯讨论:input 是 list of list of show name(每行一个横滑列表),确认了不用考虑 ranking 和 recommendation,就是纯 dedup。

我的思路:维护一个 global visited set,每行再维护一个 local visited set,逐行 loop,同时保证 global 和 local 都没有重复才加进 result。写完主动补了 test case。

最后十分钟面试官把话题引到 real production:local cache 撑不起大规模场景怎么办?我们讨论到可以用 Redis bloom filter 做分布式去重,以及它自带的 false positive 问题和权衡。这段聊天让我意识到,奈飞的”解决问题轮”其实是算法题皮、系统设计骨。

第二轮:Coding 轮

三个部分,还是跟 dedup 一个主题串下来的:

第一题类似 LeetCode 217(Contains Duplicate),input 是 list of show name,判重,set 一行解。

第二题类似 LeetCode 第三题(最长无重复子串)的变体,input 还是 show name 列表,返回连续最长没有重复 show 的子列表长度,标准 sliding window。

第三题:list of show name,找出没有公共字符的 unique pair,返回 pair 数量。我现场直接 brute force 两两比较,面试官说也行。wrap up 的时候他提了一句可以用 bitmask——每个 show name 压成 26 位的位掩码,两个 mask 按位与为 0 就是无公共字符,这是 LeetCode 318 的原型。

整体感受

奈飞的面试给我最深的印象是:题目本身不筛人,过程筛人。三道 coding 没一道是 hard,但如果你拿到题就闷头写,大概率凉——面试官故意把需求说得模糊,就是在看你会不会 clarify。所以全程要边演边写:确认输入输出、说出思路再动手、写完主动跑 test case、聊到 production 场景要能接得住。

test case 也要想全一点,空输入、全重复、单元素这些边界主动 cover,比写出 bitmask 最优解加分多得多。

备考路上我参考了 InterviewShow 整理的北美大厂 OA 题库,奈飞 CodeSignal 这几道新题都有收录和思路解析,店面的 clarification 套路在模拟面试里也能专门练,有需要的可以去看看。

END