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_transactions 和 internal_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 扣分點:
- 沒用 hashmap,對每個 internal_tx 都遍歷所有 bank_tx → O(n×m) 超時
- 忘記
break,導致同一筆交易被多次匹配 - 沒考慮 amount 為負(refund)
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 = []
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 internal_tx in list(self.pending_internal):
for bank_tx in 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 次。需支援:
dispatch(event_id, attempt_at):登記一次投遞mark_failed(event_id, failed_at):標記失敗,自動計算下一次重試時間get_due_events(now):返回所有當前應該重試的 event
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)
self.due_heap = []
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 扣分點:
- 不用 heap,每次
get_due_events全表掃描 → 大資料超時 2 ** (attempt_num - 1)寫成2 ** attempt_num導致首次重試間隔 2s 而非 1s- 沒處理 max_attempts 邊界
題目三: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
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 隱藏測試:
- 循環依賴(A → B → A):BFS 自然處理
- 浮點精度(USD→EUR→USD 不等於原值):Stripe 要求 5 位小數容差
- 不存在的貨幣:返回 None 而非拋異常
Stripe OA 答題策略總結
| 錯誤 | 扣分 | 修正 |
|---|---|---|
| 沒考慮空輸入 | 5 分/Part | 第一行寫 if not data: return [...] |
| 沒考慮負數/0 | 3 分/Part | 業務上 refund 是負數 |
| 暴力 O(n²) 解 | 0 分(超時) | 用 hashmap 或 heap |
| 函數命名縮寫 | 1 分/方法 | bank_tx 比 bt 好 |
| 沒寫單元測試 | 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