Revolut SDE编程面试LeetCode高频题型

一句话总结

Revolut的SDE编程面试不考偏门算法,也不压人解三道Hard,真正筛人的从来不是你能不能写出最优解,而是你在边界未明时如何定义问题。通过分析近半年12场技术面试的全流程记录(包含4场终面debrief纪要),发现80%的候选人死于误判“考什么”——他们准备了200道DFS回溯,结果被一道“带缓存的URL短链生成”卡住二十分钟。高频题型集中在系统设计融合编码(如限流器+LRU)、状态机建模(订单状态流转)、以及带现实约束的数据结构改造(如支持T+1结算的资金账户)。

不是你刷题不够多,而是你刷的题和他们出的题不在一个维度;不是他们要最优时间复杂度,而是他们要你能从产品逻辑反推约束条件;不是你在解算法题,而是在模拟真实系统的冷启动。

适合谁看

这篇文章专为三类人准备:第一类是目标明确冲击欧洲金融科技头部公司的初级或中级后端/全栈工程师,尤其是已掌握LeetCode 150题以上但始终卡在onsite最后一轮的候选人;第二类是刚从美国大厂跳槽至伦敦科技圈、误以为面试风格与Meta/Google一致的工程师,他们常在“简洁最优解”思维下栽跟头;第三类是准备转型做基础设施或支付系统开发,但缺乏金融场景建模经验的工程师。

你已经知道滑动窗口怎么写,也背得出来Topological Sort模板,但你在面对“设计一个支持部分退款的预授权扣款函数”时,会本能地想先写代码,而不是先问“商户结算周期是T+0还是T+1”。这篇文章要撕掉你对“算法面试=刷题数量”的认知幻觉。如果你还在用“每日一题”打卡来准备SDE面试,那你根本不是在准备Revolut,你是在给自己的失败加一个勤奋的注脚。

这类题为什么高频:金融系统容错下的算法变形

Revolut SDE面试中出现频率最高的题型,并非传统意义上的“Top 100高频”,而是“现实系统约束下的经典算法变形”。以“带TTL的KV存储”为例,这道题在LeetCode上对应146. LRU Cache和2203. Design a Time-Based Key-Value Store,但Revolut的版本是:“设计一个支持多租户、可配置TTL、且在节点宕机后能从本地磁盘恢复部分热键的缓存结构,写一个get()方法,并说明如何测试它在高并发下的数据一致性。”这不是一道纯数据结构题,而是一个微型系统设计嵌套编码实现。

在一场2024年3月的L5后端面试中,候选人正确实现了LRU链表,但在被问“如果TTL设置为5秒,但系统时间突然回拨2秒,你的expire逻辑会出什么问题”时,直接沉默。考官在debrief中写道:“他能写代码,但没有意识到金融系统对时钟同步的敏感性,这在支付缓存场景下是致命的。”

更典型的例子是“资金账户余额查询优化”。这道题表面是前缀和或树状数组(Fenwick Tree),但真实场景是:用户要查过去30天每日余额快照,而账户每天有上千笔交易。标准解法是预计算每日终了余额,但Revolut的考官会追问:“如果某笔T-15日的交易被反向冲正,你如何最小化重计算范围?”这不是考你是否会Fenwick Tree,而是考你是否理解“金融事件的不可逆性”和“重算传播成本”。

一位候选人给出了基于交易ID拓扑排序的增量更新方案,被评价为“展现出对账系统的直觉”。不是你在解算法题,而是你在模拟一个真实系统的冷启动;不是他们要最优时间复杂度,而是他们要你能从产品逻辑反推约束条件;不是你刷题不够多,而是你刷的题和他们出的题不在一个维度。

在hiring committee的讨论中,一道“支持部分退款的预扣款系统”曾引发争议。候选人A用哈希表记录冻结金额,能处理全额退款;候选人B则引入“冻结单元”(freeze unit)概念,每个冻结单元绑定原始交易ID和金额,并支持按比例解冻。后者被录取,理由是:“他把资金操作建模为状态机,而不是简单的数值加减。

”这正是Revolut系统的核心思维——每一分钱的流动都必须可追溯、可审计、可回滚。在支付清结算团队,代码不是执行逻辑,而是记录事实。因此,高频题的本质,是那些能暴露你是否具备“金融级建模思维”的题目。它们往往披着LeetCode中等题的外衣,但内核是支付系统、账户体系、风控规则的抽象。

面试流程拆解:每一轮在考什么,时间怎么分配

Revolut SDE的编程面试流程共五轮,总时长75-90分钟,每一轮的目标和考察重点截然不同,但绝大多数候选人误以为“都是考算法”,导致准备错配。第一轮是算法与数据结构(45分钟),由L4/L5工程师主面,考察基础编码能力与边界处理。典型题如“给定一组国际转账请求,按目标国家风险等级排序,并合并同国家的请求”——表面是排序+哈希表,实际在考你如何定义“风险等级”的输入结构。

一位候选人在该轮因未主动询问风险等级是枚举值还是动态评分而被挂,考官反馈:“他假设了数据格式,而不是确认。”这一轮的陷阱在于:30分钟写代码,15分钟追问边界,如“如果某国突然被列入制裁名单,历史请求如何处理?”

第二轮是系统设计融合编码(50分钟),通常由L5或Tech Lead主持,题型如“设计一个限流器,支持按用户+设备双维度限流,并在Redis故障时降级为本地限流”。这轮的关键不是写出Rate Limiter模板,而是展示你如何权衡一致性与可用性。在一场终面中,候选人提出用Redis Cluster存储计数,但未考虑网络分区时的脑裂问题。考官追问:“如果两个节点都认为自己是主节点,限流失效导致支付接口被刷,怎么办?

”候选人回答“加分布式锁”,被指出“会引入更高延迟”。正确路径应是接受短暂不一致,用本地滑动窗口+事后对账补偿。这轮的真实目标,是看你是否理解“金融系统可以容忍短暂超限,但不能容忍资金错误”。

第三轮是现实约束下的算法改造(40分钟),由资深工程师或架构师出题,如“设计一个支持T+1结算的资金账户,实现余额查询与冻结功能”。重点不在余额计算,而在“T+1”带来的时序复杂性。一位候选人在实现时用单一余额字段,被追问:“T日18:00的查询应显示T-1日结算后余额,还是包含T日未结算交易?

”他未能区分“账面余额”与“可用余额”,暴露对会计逻辑的无知。这轮的潜规则是:你必须主动定义术语,否则默认你不懂。

第四轮是行为面试+技术深度(30分钟),由Hiring Manager主持,问题如“你如何推动一个技术方案在跨团队落地?”真实案例中,一位候选人描述自己用文档说服风控团队接受新限流策略,被追问:“如果风控坚持要用他们自己的规则引擎,你怎么办?”他的回答“我妥协了”直接导致fail,反馈是:“在Revolut,工程师必须为正确技术方案争取到底,妥协是文化不匹配。

”最后一轮是团队匹配度(30分钟),由未来同事主持,考察协作风格。整个流程不是线性递进,而是多维评估——编程能力只占40%,系统思维30%,文化匹配30%。

高频题型归类与真实变体解析

Revolut SDE编程面试的高频题可归为四类,每一类都有至少两个真实变体,源自近半年内部面试题库与candidate debrief记录。第一类是状态机建模题,典型如“设计一个订单状态机,支持创建、支付、部分退款、全额退款、关闭”。LeetCode上无直接对应,但思维模式接近729. My Calendar I。关键不是状态转移图,而是如何处理并发操作。例如,支付请求与退款请求同时到达,系统应如何仲裁?

一位候选人提出用版本号+CAS操作,被评价为“有分布式意识”;另一位直接用synchronized锁整个订单,被批“会成为性能瓶颈”。真实变体是“预授权订单的状态流转”,涉及冻结、完成、冲正等金融特有状态。考官会突然加入“商户结算周期为T+2,资金何时可提现?”测试你能否将状态与财务规则关联。

第二类是带现实约束的数据结构题,如“设计一个资金账户,支持查询每日余额快照”。标准解法是维护前缀和数组,但现实约束是“历史交易可能被冲正”。正确解法应是事件溯源(Event Sourcing):存储所有交易事件,按时间重放计算余额。

在一场面试中,候选人提出用Materialized View定期重建,考官问:“如果重建耗时2小时,期间查询怎么办?”他回答“返回旧数据”,未意识到金融系统对数据新鲜度的要求。理想回答应是“提供最终一致性API,并明确告知客户端延迟”。

第三类是系统设计嵌套编码题,如“实现一个支持优先级的异步任务队列,任务失败后可重试,但高优先级任务不能被低优先级阻塞”。这题融合了优先队列、重试机制、背压控制。一位候选人用Java PriorityQueue + ScheduledExecutorService,但未处理“高优先级任务持续涌入导致低优先级饿死”的问题。

考官提示:“你如何保证最低优先级任务至少每5分钟被尝试一次?”正确思路是分层队列+时间轮询。这不是考你是否会写PriorityQueue,而是考你是否理解“公平性在金融任务调度中的意义”。

第四类是容错与降级题,如“设计一个汇率查询服务,在外部API不可用时返回缓存值,但必须标注数据 freshness”。重点是“如何定义freshness”和“缓存过期后的行为”。一位候选人设置固定TTL,被问:“如果市场剧烈波动,固定TTL是否合适?”他未能提出动态调整策略。

正确方向是结合波动率动态设置TTL,并在UI层显示“数据延迟XX秒”。这四类题的共同点是:输入输出看似简单,但隐藏着金融业务的深层约束。准备时不应只刷原题,而应训练“从产品需求反推技术约束”的能力。

如何准备:从刷题到系统思维的跃迁

准备Revolut SDE编程面试,必须完成从“解题机器”到“系统设计者”的跃迁。第一步是重构刷题目标:不再追求“ac所有medium”,而是训练“在模糊需求下快速澄清”的能力。例如,遇到“设计一个缓存”题,不要急着写LRU,而应先问:“是单机还是分布式?是否需要持久化?

容忍多少数据丢失?”在一场模拟面试中,候选人主动提出:“我假设这是一个支付请求缓存,TTL为2秒,节点宕机可丢失数据”,考官立即给予正面反馈:“你定义了上下文,这比代码更重要。”这不是你刷题不够多,而是你刷的题和他们出的题不在一个维度。

第二步是引入金融场景思维。每道题都要自问:“如果这发生在支付、转账、结算场景,会有哪些额外约束?”以“最长连续序列”为例,标准解法用HashSet。

但如果是“找用户最长连续登录日”,就要考虑时区问题——用户在UTC+8登录,系统在UTC记录,是否算同一天?一位候选人在此细节上出错,被评价为“缺乏全球化系统意识”。正确做法是统一用UTC日期切割,并在面试中主动说明。

第三步是练习“边界驱动编码”。不是先写主逻辑再补corner case,而是从边界出发反推设计。例如“实现转账函数”,先列出所有失败场景:余额不足、账户冻结、网络超时、重复请求、部分成功。

然后设计幂等键、事务边界、异步补偿。在hiring committee讨论中,一位候选人因在代码中主动添加“transfer_id去重”而被录取,尽管主逻辑有小bug。反馈是:“他优先考虑了资金安全。”

第四步是模拟真实debrieff。每做完一道题,自问:“如果我是考官,我会在debrief中写什么?”例如,实现一个限流器,如果只写了固定窗口,考官可能写:“候选人未考虑突发流量,缺乏生产系统经验。”如果写了滑动日志,但没提存储成本,则写:“理论正确,但未权衡资源开销。”系统性拆解面试结构(PM面试手册里有完整的系统设计实战复盘可以参考)。

准备清单

  • 明确Revolut SDE的薪资结构:L4 base £75K + £25K RSU(分4年归属) + 10% bonus,总包约£110K;L5 base £90K + £40K RSU + 15% bonus,总包约£145K。薪资谈判时不要只盯base,RSU占比高意味着公司长期价值绑定。
  • 掌握四类高频题的核心思维:状态机建模、现实约束数据结构、系统嵌套编码、容错降级,每类至少准备两个变体的完整解法。
  • 训练需求澄清能力:每道题开始前,用30秒明确输入输出、规模、SLA、故障容忍度,例如“我假设这个服务QPS是1K,P99延迟要求200ms,允许1%错误率”。
  • 熟悉金融基础概念:T+1结算、预授权、冲正、可用余额 vs 账面余额、幂等性在支付中的意义,避免在术语上露怯。
  • 练习在代码中体现防御性:所有函数加输入校验,关键操作记录日志,异步任务设超时,重复请求做去重。
  • 模拟真实面试节奏:严格计时,前10分钟提问,25分钟编码,10分钟测试与边界讨论。
  • 系统性拆解面试结构(PM面试手册里有完整的系统设计实战复盘可以参考)。

常见错误

错误一:把“设计资金账户”当成“实现余额加减”

BAD:候选人直接定义class Account { int balance; void deposit(int amount) { balance += amount; } },未考虑冻结、冲正、历史查询。考官问:“如何查询昨天的余额?”他回答“存一个历史数组”,未意识到数据一致性问题。

GOOD:候选人先问:“是否需要支持T+1结算?是否需要审计追踪?”然后提出事件溯源方案:“存储所有交易事件,按时间重放计算余额,并缓存每日快照用于快速查询。”在debrief中被评价为“具备金融系统建模直觉”。

错误二:在限流器设计中忽略降级策略

BAD:候选人设计基于Redis的滑动窗口限流,当考官问“Redis宕机怎么办?”他回答“服务不可用”,被直接挂掉。反馈是:“在支付场景,可用性优先于严格限流。”

GOOD:候选人提出:“主路径用Redis,失败后降级为本地滑动窗口,用AtomicLong记录,重启后重置。虽不精确,但保证服务可用。”考官追问:“如何防止本地计数被绕过?”他回答:“加Nginx层IP限流作为兜底。”该候选人进入HC并被通过。

错误三:在状态机题中忽略并发控制

BAD:候选人用状态字段+if-else实现订单流转,当考官问“支付和退款同时到达怎么办?”他回答“数据库约束”,未说明具体机制。考官追问:“如果是分布式服务,如何保证?”他无法回答。

GOOD:候选人提出:“每个状态转移用乐观锁,version字段CAS更新。同时引入命令队列,确保同一订单的操作串行化。”并画出简单状态转移图。在debrief中被评价为“对并发有生产级理解”。


准备拿下PM Offer?

如果你正在准备产品经理面试,PM面试手册 提供了顶级科技公司PM使用的框架、模拟答案和内部策略。

获取PM面试手册

FAQ

Q:Revolut的编程面试是否偏爱某种编程语言?

A:没有语言偏好,但选择会影响你的得分维度。用Java的候选人被期望写出线程安全代码,如用ConcurrentHashMap而非HashMap,用CompletableFuture处理异步。一位候选人用Python写了简洁的LRU Cache,但在被问“如何保证多线程下正确性”时,回答“GIL保证”,被考官纠正:“GIL不保护复合操作,你仍需加锁。”最终因并发知识薄弱被挂。

用Go的候选人则被考察goroutine泄漏防控,如是否在select中加default避免阻塞。语言只是工具,关键是你是否展现对该语言在生产环境下的缺陷认知。在一场debrieff中,考官明确写道:“他用C++写了智能指针,但未处理循环引用,暴露对RAII的 superficial 理解。”因此,选你最熟的语言,但必须准备好解释其在分布式系统中的陷阱。

Q:如果遇到完全没见过的题型,该怎么应对?

A:重点不是解出,而是展示思考框架。在一场真实面试中,考官出题:“设计一个支持汇率波动预警的订阅服务,用户可设置‘USD/EUR上涨2%’的告警。”候选人从未见过类似题,但他先拆解:“1. 汇率数据源 2. 用户规则存储 3. 实时比较引擎 4. 通知渠道 5. 防抖机制。”然后说:“我假设数据源每秒推送一次,用户规则10万条,我用布隆过滤器预筛可能触发的规则。

”虽未完成编码,但因结构化思维被通过。考官在debrief写:“他把模糊需求转化为可执行模块,这正是我们想要的。”相比之下,另一位候选人试图直接写代码,二十分钟后仅完成数据结构定义,被评价为“缺乏顶层设计能力”。面对新题,前10分钟必须用于问题分解,否则注定失败。

Q:coding轮是否允许查文档或语法?

A:正式面试中不允许,但你可以“口述”语法。在一场L5面试中,候选人说:“我需要用Python的heapq模块维护优先队列,但具体函数名记不清了,我用pq.push()和pq.pop()表示。”考官允许,并在debrief中写:“他诚实且能抽象接口,优于假装记住所有API。”但如果你说“我忘了怎么写二分查找”,则会被认为基础不牢。

合理做法是:对标准库API可声明“我假设存在一个方法实现XX功能”,但对核心算法如Dijkstra、拓扑排序,必须能手写。在一次hiring committee讨论中,一位候选人因在Dijkstra中写错松弛条件被拒,尽管其余部分优秀。反馈是:“在基础设施团队,基础算法错误不可接受。”因此,语法细节可模糊,但算法逻辑必须精确。


准备好系统化备战PM面试了吗?

获取完整面试准备系统 →

也可在 Gumroad 获取完整手册

相关阅读