SWE · Coding

照片Iterator:先favorite,再普通列表,过滤blocked和重复

顺序稳定且不提前读尽所有输入,迭代状态只保存必要去重。

题目重点:顺序稳定且不提前读尽所有输入,迭代状态只保存必要去重。

题意与假设

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

  • ID可哈希,blocked为固定快照;favorites与photos分别有序。
  • 先输出全部有效favorites,再输出photos中未输出且未blocked者;重复ID只输出一次。

解题路线

  1. 依次遍历两个source,每ID先检查blocked再seen,通过才放seen并yield。整个算法不按ID排序,保留原到达顺序。
  2. yield暂停直到消费者要下一个;如果favorites是无限流,永远到不了普通photos,接口需要限制或定义公平交织,但那会改变“favorite全部优先”。
  3. blocked快照避免迭代中权限变化语义模糊;若blocked是实时权限,需每次输出前重新核对且讨论已输出内容无法撤回。

手动走一遍

favorite=[B,A,B],photos=[A,C,D],blocked={C}输出B,A,D。消费者只取第一项时不应预读完整photos;blocked和seen需要的读取仍可能让一次next跳过很多项。

Python 参考实现

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

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

def photo_iterator(favorites,photos,blocked):
    blocked=frozenset(blocked)
    seen=set()
    for source in (favorites,photos):
        for ident in source:
            if ident not in blocked and ident not in seen:
                seen.add(ident)
                yield ident

复杂度

总读取N、有效输出D,期望O(N)时间、O(D+B)状态;单次next最坏可扫描大量被过滤项,不能声称每next最坏O(1)。

易错点与追问

容易失分的边界

  • 只对各列表内部去重不够,还要跨列表去重。
  • seen应只记真正输出的ID,特别当blocked规则扩展时需明确语义。

继续深挖

  • hasNext怎样预取一个有效项又不重复消费?
  • 独立两个iterator是否各自有seen,共享输入生成器会有什么限制?
✓已复制微信号!