‹ 全部面经
Amazon VO 面经:BQ 深挖 + 有限算力的文档处理设计 + Alexa 对话切分会话
Amazon VO 复盘:BQ 问 scope creep、时间紧任务重的取舍、主动争取资源;系统设计在 QPS 受限下最大化海量文档处理产出;Coding 按 60 秒间隔切分 Alexa 对话会话,Follow-up 乱序插入。
Amazon
VO
Amazon 的 VO 面试官问得真的非常深!行为问题、系统设计题、编程题都有追问,全程问题不大,依旧稳定应付。
行为问题
主要问了这几个点:
- 需求变来变去怎么办? 比如项目进行到一半,突然加新需求(scope creep),你是怎么处理的?
- 时间紧任务重怎么做取舍? 比如为了赶进度,是不是用过一些临时方案,或者把流量隔离开?
- 有没有主动找老板要资源? 比如发现事情做不完,会不会主动跟经理沟通、重新排优先级?
系统设计题
题目:假设每秒能处理的请求数有限,但要处理海量的文档数据,怎么才能让产出的有用结果最大化?
我的思路:
- 按优先级分批处理
- 去掉重复的文档
- 用缓存加速
- 排队限流
- 动态调整批次大小
这样就能把有限的处理能力用到极致。
编程题:Alexa 对话切分会话
题目:把用户和 Alexa 的对话按时间切成一段段的「会话」。规则:两次说话间隔不超过 60 秒就算同一个会话;超过 60 秒就开始新的会话。
解法:先把所有记录按时间排序,然后依次看相邻两条记录的时间差。小于等于 60 秒就归到当前会话;超过了就把当前会话存起来,开启一个新会话。最后返回所有会话的列表。
def split_sessions(records, gap=60):
"""records: [(timestamp, text)],返回会话列表,每个会话是按时间排好的记录"""
sessions = []
for rec in sorted(records, key=lambda r: r[0]):
if sessions and rec[0] - sessions[-1][-1][0] <= gap:
sessions[-1].append(rec)
else:
sessions.append([rec])
return sessions
Follow-up:对话乱序到达怎么办?
追问:如果对话不是按顺序来的,而是陆陆续续插进来的(不一定在最后),怎么把它加到正确的会话里?
当时的解答:遍历现有的所有会话,拿新来的记录去和每个会话的最后一条比较时间。时间差在 60 秒内就追加进去;都不行就只能新建一个会话。
补充优化:会话之间按开始时间是有序的,可以用二分找到新记录前后相邻的两个会话,不用遍历全部,O(log S) 定位。还有一个容易漏的情况:新记录可能刚好填上两个会话之间的空隙,这时要把前后两个会话合并成一个。
from bisect import bisect_right
def insert_record(sessions, rec, gap=60):
"""sessions 按开始时间有序,原地插入一条新记录"""
t = rec[0]
i = bisect_right([s[0][0] for s in sessions], t) # sessions[i-1] 开始于 t 之前
join_prev = i > 0 and t <= sessions[i - 1][-1][0] + gap
join_next = i < len(sessions) and sessions[i][0][0] - t <= gap
if join_prev and join_next: # 填上空隙,前后合并
sessions[i - 1:i + 1] = [sessions[i - 1] + [rec] + sessions[i]]
sessions[i - 1].sort(key=lambda r: r[0])
elif join_prev:
sessions[i - 1].append(rec)
sessions[i - 1].sort(key=lambda r: r[0])
elif join_next:
sessions[i].insert(0, rec)
else:
sessions.insert(i, [rec])