← 返回博客列表 Stripe OA 真题分享:2026 春招实测题型与避坑清单|一亩三分地
Stripe

Stripe OA 真题分享:2026 春招实测题型与避坑清单|一亩三分地

2026-05-13

Stripe OA 在所有金融科技公司中风格最独特——不考算法 Hard 题,但隐藏测试用例多达 15-20 个,常常出现"思路对、代码错"的尴尬情况。本文汇总 2026 春招(Q1-Q2)一亩三分地最新的 Stripe OA 真题分享,按出现频率排序给出三道实战原题、完整 Python 解法以及评分系统的扣分细节。所有题目来源于 2026 年 1-4 月的真实候选人反馈,与既往 brace expansion、shipping cost 等老题完全不同

Stripe 2026 春招 OA 概览

维度 详情
平台 HackerRank for Work
总时长 120 分钟
题量 通常 1 道大题(分 4 个 Part)
难度 单题 LeetCode Easy ~ Medium,但 Part 间难度递增
隐藏测试 15-20 个,每个 Part 5-7 个
通过线 80%+ 测试通过

题目一:Payment Reconciliation(支付对账,出现率最高)

Part 1:基础对账

题意:给定两个数据源 bank_transactionsinternal_records,每条数据是 (transaction_id, amount, timestamp)。返回只在内部记录中存在、银行未确认的交易。

def find_unreconciled(bank_transactions, internal_records):
    """
    bank_transactions: List[Tuple[str, int, int]]
    internal_records: List[Tuple[str, int, int]]
    return: List[Tuple[str, int, int]],按 timestamp 升序
    """
    bank_ids = {tx[0] for tx in bank_transactions}
    unreconciled = [r for r in internal_records if r[0] not in bank_ids]
    unreconciled.sort(key=lambda x: x[2])
    return unreconciled

时间复杂度:O(n + m log m),n 为银行交易数,m 为内部记录数。

Part 2:金额匹配但 ID 不一致

题意:在 Part 1 的"未对账"中,找出金额相同、时间戳差 ≤ 60 秒的交易对。可能是同一笔交易但 ID 写错了。

from collections import defaultdict

def find_fuzzy_matches(unreconciled, bank_transactions, time_tolerance=60):
    """
    在 unreconciled 中,找出可以与 bank_transactions 模糊匹配的交易对
    """
    # 按金额分桶
    bank_by_amount = defaultdict(list)
    for tx in bank_transactions:
        bank_by_amount[tx[1]].append(tx)
    
    matches = []
    for internal_tx in unreconciled:
        amount = internal_tx[1]
        for bank_tx in bank_by_amount[amount]:
            if abs(bank_tx[2] - internal_tx[2]) <= time_tolerance:
                matches.append((internal_tx, bank_tx))
                break
    
    return matches

Stripe 扣分点

Part 3:批量对账与冲突解决

题意:当多笔内部交易可以匹配同一笔银行交易时,按 timestamp 最近原则分配。

def assign_conflicts(unreconciled, bank_transactions, time_tolerance=60):
    bank_by_amount = defaultdict(list)
    for tx in bank_transactions:
        bank_by_amount[tx[1]].append(tx)
    
    used_bank = set()
    result = []
    # 按 internal_tx 时间戳排序,先到先得
    unreconciled_sorted = sorted(unreconciled, key=lambda x: x[2])
    
    for internal_tx in unreconciled_sorted:
        amount = internal_tx[1]
        best_match = None
        best_diff = time_tolerance + 1
        for bank_tx in bank_by_amount[amount]:
            if bank_tx[0] in used_bank:
                continue
            diff = abs(bank_tx[2] - internal_tx[2])
            if diff < best_diff:
                best_diff = diff
                best_match = bank_tx
        
        if best_match:
            used_bank.add(best_match[0])
            result.append((internal_tx, best_match))
    
    return result

Part 4:流式对账(State Reset)

最难的一 Part:要求实时处理流式输入,每条新交易立即匹配或挂起,超过 5 分钟未匹配则标记为"待人工审核"。

from collections import deque

class StreamReconciler:
    def __init__(self, time_tolerance=60, escalation_timeout=300):
        self.time_tolerance = time_tolerance
        self.escalation_timeout = escalation_timeout
        self.pending_internal = deque()  # 待匹配的内部交易
        self.pending_bank = deque()
        self.matched = []
        self.escalated = []
    
    def process(self, tx_type, tx):
        if tx_type == "internal":
            self.pending_internal.append(tx)
        else:
            self.pending_bank.append(tx)
        
        self._try_match(tx[2])
        self._escalate_old(tx[2])
    
    def _try_match(self, current_time):
        for i, internal_tx in enumerate(list(self.pending_internal)):
            for j, bank_tx in enumerate(list(self.pending_bank)):
                if (internal_tx[1] == bank_tx[1] and 
                    abs(internal_tx[2] - bank_tx[2]) <= self.time_tolerance):
                    self.matched.append((internal_tx, bank_tx))
                    self.pending_internal.remove(internal_tx)
                    self.pending_bank.remove(bank_tx)
                    return self._try_match(current_time)
    
    def _escalate_old(self, current_time):
        while self.pending_internal and current_time - self.pending_internal[0][2] > self.escalation_timeout:
            self.escalated.append(self.pending_internal.popleft())
        while self.pending_bank and current_time - self.pending_bank[0][2] > self.escalation_timeout:
            self.escalated.append(self.pending_bank.popleft())

题目二:Webhook 重试系统(出现率 30%)

题意

实现 Stripe Webhook 的指数退避重试逻辑。每次 webhook 投递失败后,下次重试间隔翻倍(1s, 2s, 4s, 8s, ...),最多重试 8 次。需支持:

from collections import defaultdict
import heapq

class WebhookRetrySystem:
    def __init__(self, max_attempts=8, base_delay=1):
        self.max_attempts = max_attempts
        self.base_delay = base_delay
        self.attempts = defaultdict(int)  # event_id -> attempt count
        self.due_heap = []  # min-heap of (retry_time, event_id)
        self.failed_permanently = []
    
    def dispatch(self, event_id, attempt_at):
        self.attempts[event_id] += 1
    
    def mark_failed(self, event_id, failed_at):
        attempt_num = self.attempts[event_id]
        if attempt_num >= self.max_attempts:
            self.failed_permanently.append(event_id)
            return
        delay = self.base_delay * (2 ** (attempt_num - 1))
        retry_time = failed_at + delay
        heapq.heappush(self.due_heap, (retry_time, event_id))
    
    def get_due_events(self, now):
        due = []
        while self.due_heap and self.due_heap[0][0] <= now:
            _, event_id = heapq.heappop(self.due_heap)
            due.append(event_id)
        return due

Stripe 扣分点

题目三:Currency Conversion Graph(出现率 25%)

题意

给定一组货币汇率 rates = [(from, to, rate), ...],实现一个 convert(from_currency, to_currency, amount) 方法。如果没有直接汇率,需要找出中间转换路径

from collections import defaultdict, deque

class CurrencyConverter:
    def __init__(self, rates):
        self.graph = defaultdict(dict)
        for from_cur, to_cur, rate in rates:
            self.graph[from_cur][to_cur] = rate
            self.graph[to_cur][from_cur] = 1.0 / rate  # 双向
    
    def convert(self, from_cur, to_cur, amount):
        if from_cur == to_cur:
            return amount
        if from_cur not in self.graph:
            return None
        
        # BFS 找最短路径
        queue = deque([(from_cur, amount)])
        visited = {from_cur}
        
        while queue:
            current_cur, current_amount = queue.popleft()
            if current_cur == to_cur:
                return current_amount
            for neighbor, rate in self.graph[current_cur].items():
                if neighbor not in visited:
                    visited.add(neighbor)
                    queue.append((neighbor, current_amount * rate))
        
        return None  # 不可达

测试

rates = [
    ("USD", "EUR", 0.9),
    ("EUR", "GBP", 0.85),
    ("GBP", "JPY", 180),
]
conv = CurrencyConverter(rates)
print(conv.convert("USD", "JPY", 100))  # 100 * 0.9 * 0.85 * 180 = 13770.0

Stripe 隐藏测试

Stripe OA 答题策略总结

错误 扣分 修正
没考虑空输入 5 分/Part 第一行写 if not data: return [...]
没考虑负数/0 3 分/Part 业务上 refund 是负数
暴力 O(n²) 解 0 分(超时) 用 hashmap 或 heap
函数命名缩写 1 分/方法 bank_txbt
没写单元测试 5 分总分 至少加 3 个 assert

FAQ

Stripe OA 一定要做完所有 Part 吗?

不一定。Stripe 评分采用绝对分数 + Part 完成度双指标。如果 Part 1+2 全对(约 60%),通过率仍然有 30%。优先保证前两个 Part 100% 正确,再尝试 Part 3。

Stripe OA 可以查 Google 吗?

理论上禁止(HackerRank 摄像头会记录),但实际监管不严。建议查文档(如 heapq 用法)但不要查算法答案——评分员会看代码风格识别"非候选人原创"。

Stripe OA 通过后多久会有反馈?

通常 5-10 个工作日。Stripe HR 节奏稳定,不通过会发明确拒信(这点比 Google、Meta 友好)。

这些题目和 1point3acres 上面经一致吗?

是。本文所有题目来自 2026 Q1-Q2 一亩三分地 Stripe 板块的真实分享,但变量名和 Part 划分会随每个 candidate 略有不同——Stripe 的题库每月轮换一次。

Stripe OA 推荐用什么语言?

Python(首选)、JavaScript(次选)。Stripe 内部主要用 Ruby,但 OA 不强制——评分员只看正确性。避免 C++:Stripe OA 的字符串处理多,C++ 写起来慢。


正在准备 Stripe OA?

oavoservice 持续整理 Stripe 真题(包括本文未覆盖的 brace expansion、shipping cost、subscription notifications 等老题),提供 OA 限时模拟与隐藏测试用例预演。导师团队包括前 Stripe Engineer,熟悉评分系统的所有扣分点。

立即添加微信:Coding0201获取 Stripe OA 真题包

#Stripe #OA #支付系统 #Webhook #真题分享 #一亩三分地


联系方式

Email: [email protected]
Telegram: @OAVOProxy