Robinhood 的面试还挺注重 communication 的,不光要写对 code,还得讲清楚你是怎么想的。我面的三轮基本都是 LeetCode medium+system design,没有特别离谱的难题,但 follow up 问得挺细,得把 trade-off 讲明白才行。

第一轮 coding
题目:Robinhood有个推荐系统:老用户推荐新用户加入,每条推荐关系只能发生一次,不会有循环推荐。我们想知道哪些用户的“推荐链”最厉害,统计每位用户最终带来的新用户总数,然后列出影响力前三名。
解题思路:首先整理推荐数据,用字典记录“推荐人-直接推荐用户列表”,确保每个新用户仅归属1个推荐人,然后对每个用户,遍历其推荐链,统计不重复的新用户总数,最后按“推荐总数降序、用户名升序”排序,截取前三名并按“用户名 推荐数量”格式输出即可。 本质是处理“无环单向图”的节点后代数量统计问题。
第二轮coding
题目:给定一个由“买入”和“卖出”订单组成的订单流,需要计算订单的总成交数量。
解题思路: 用有序结构存未成交单:买入单按价格降序,快速找高价买单,卖出单按价格升序,快速找低价卖单,均记录“价格+剩余数量”,然后逐笔处理订单,买单打匹配价相等卖单,卖单打匹配价≥自身的买单,取最小量成交并累加总数,剩余订单更新或留存,最后等所有订单处理完,输出总成交数。
第三轮:Design a Leaderboard
题目:Design a leaderboard with the following APIs:addScore(playerId, score) top(K)
reset(playerId)
这题其实是数据结构设计题。我当时跟面试官讨论了几个方案:
方案一:hashmap + 每次 topK 时排序。优点是简单,缺点是大规模数据下 topK 效率低。
方案二:hashmap + 最小堆(size K)。addScore 的时候更新 hashmap,topK 的时候遍历 hashmap 维护一个大小为 K 的 min-heap。但这里有个坑:如果已经维护了一个全局堆,reset 或者 addScore 更新分数时,堆里可能有脏数据。所以要么惰性删除,要么用 balanced BST。
方案三:hashmap + TreeMap(或者 sorted set)。用 TreeMap 维护分数到 playerId list 的映射,这样 topK 可以直接取最大 key。面试官对这个方案比较认可,说空间换时间,思路清晰。
最后讨论
面试官最后抛了一个open-ended 问题:如果这个 leaderboard 在高并发场景下怎么办?可以考虑几个方向:
- 读写分离
- 缓存 topK
- 异步批量更新
- 分布式排行榜(分片)
这种问题一般不需要特别完整的答案,主要是看你的系统设计思路。
面试卡住怎么办
其实很多同学在技术面的时候不是不会做题,而是现场压力大、思路容易断,尤其是像Robinhood 这种 follow up 很多的面试,一旦某一步没想清楚,就可能被一路追问卡住。
如果你也担心在 VO 或技术面里出现这种情况,可以提前了解一下programhelp的 面试辅助 ,在你面试过程中如果遇到卡点,可以得到思路提醒和方向提示。