题目重点:合并 Nvidia DGX Cloud 的 FizzBuzz 与 Senior Cloud Infra 的数字到字母扩展信号,给出除数映射训练契约、多个规则同时命中与缓存取舍。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 训练版 map 的 key 是正整数除数、value 是输出字符串;对输入整数 n,把所有整除 n 的规则文字按除数升序拼接,无命中输出 n 的字符串。题目未固定规则优先级。
- 允许输入数字为零或负数,Python `%` 用于整除判定;若实际面试只给 1..N,范围应以题面为准。
- 重复查询可做 memo,但只有当 map 在缓存生命周期内不可变或版本化时才安全;题目未明确更新规则。
解题路线
- 先实现标准规则 `{3:'Fizz',5:'Buzz'}`,再把规则抽成有序 `(divisor,word)` 列表;每个查询扫描规则并拼接命中的文字。
- 必须先问同一数字命中多个规则时如何排序、map 重复除数/空字串如何处理。示例代码定义升序,不能把它当作 Nvidia 固定题面。
- 如果相同 n 查询很多且规则固定,用 `(rules_version,n)` 缓存输出;若只查询区间 1..N,可预计算。若除数有有限最小公倍数 L,结果形式对 n mod L 有周期性,但无命中时还要返回 n 本身,且 L 可能极大,不能盲目建整周期表。
手动走一遍
训练规则 `{3:'Fizz',5:'Buzz',7:'Pop'}`:n=15 命中 3/5,输出 FizzBuzz;n=21 命中 3/7,输出 FizzPop;n=8 无命中,输出 '8'。若规则改变,之前缓存的 15 必须失效或换版本键。
Python 参考实现
下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。
代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。
def fizzbuzz_with_rules(numbers, rules):
"""Training rule: concatenate matches in ascending divisor order."""
if any(not isinstance(divisor, int) or divisor <= 0 for divisor in rules):
raise ValueError("divisors must be positive integers")
ordered = sorted(rules.items())
result = []
for number in numbers:
label = "".join(str(word) for divisor, word in ordered if number % divisor == 0)
result.append(label or str(number))
return result
复杂度
R 条规则、Q 个查询,规则排序 O(R log R),逐次扫描 O(QR) 加输出长度;缓存对不同 n 至多 O(U) 条目和输出字节,U 为唯一查询数。若一次调用重复构造排序,应把有序规则放到可复用对象。
易错点与追问
容易失分的边界
- 仅支持 3/5,map 追问无法扩展。
- 多规则命中时迭代普通 map 却未定义输出顺序。
- 规则可更新仍按旧规则缓存结果。
- 把谐音题号确定为完整输入/输出规则,忽略题目缺失的 map 语义。
继续深挖
- map 的 key 若不是除数,而是数字范围或优先级,应怎样重新建模?
- 上亿次重复 query 的缓存容量和失效如何设计?
- 要输出 1..N 时,流式生成比一次存全部结果有什么差别?
