题目重点:负offset必须读取流结束,前缀则可提前停止。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- offset≥0取前offset项;offset<0取后|offset|项;超长度返回全部可用,0返回空。
- 流有限且只读一次,不要求返回后能重读已消费部分。
解题路线
- 正数用最多k次next即可,不预读第k+1项。负数用容量k的deque,每新项自动淘汰最老,结束后队列就是后k项。
- 区别成本:前缀在无限流也可终止;后缀需要明确end-of-stream,在无限流上没有最终答案。
- 若hasNext/getNext来自外部接口,确认hasNext是否有读取副作用及调用异常;deque仍只保存已消费最后k项。
手动走一遍
a,b,c,d,e,offset2返回a,b;offset−3返回c,d,e。长流tail2总状态最多2项;offset0完全不消费流。
Python 参考实现
下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。
代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。
from itertools import islice
from collections import deque
def select(stream,offset):
if offset>=0:return list(islice(stream,offset))
return list(deque(stream,maxlen=-offset))
复杂度
前缀O(min(k,n))时间/输出空间;后缀O(n)时间、O(min(k,n))空间。不是两者都O(k)读取。
易错点与追问
容易失分的边界
- 负offset不能从前往后只读k项就得到尾部。
- 为验证流足够长而多读一个元素会影响后续消费者,需约定。
继续深挖
- 需要返回iterator而非列表时,tail是否还能即读即产?
- 流可暂时无数据但尚未结束,怎样区分暂时空与真正EOF?
