焦点关键词相关的博文配图,直观展示核心内容

Meta OA 面经 2026:账户系统九题深度拆解

Meta OA 面经 2026:账户系统九题深度拆解

Meta OA 面经 2026 是 2026 年高频真题。
首先,这是我们学员贡献的最新面经。
其次,这组内容也是 2026 年最新的面试经验。
与此同时,题目覆盖九个接口。
它重点考查状态一致性。

2026 面试流程深度复盘:Meta OA 面经 2026

首先,面试常从 createAccount 开始。
然后会接 depositpay
具体来说,这一段看返回语义。
你要先定义 Optional 规则。

此外,第二段会进入 transfer
随后会加 accept 与过期机制。
与此同时,面试官会追问扫描时机。
这个点在 Meta OA 面经 2026 很关键。

但是,第三段才是拉分题。
你会遇到 mergeAccountsgetBalance
换句话说,Meta OA 面经 2026 在考状态机。
你要把当前态和历史态分开。

因此,建议你先口述数据结构。
再写核心路径。
最后补边界测试。
这样节奏会更稳。

核心题目解析

首先,下面是九题速记清单。
每条都按判分口径写。
这样你能快速对齐 Meta OA 面经 2026。

  1. 首先,createAccount 只允许新 ID。否则返回 false
  2. 其次,deposit 遇到不存在账户时返回空。成功后返回新余额。
  3. 此外,pay 先判余额。不足或不存在都返回空。
  4. 与此同时,topActivity 统计 deposit + pay。被 accept 的转账也计入双方。
  5. 具体来说,transfer 先扣源账户并冻结。冻结期不计入 Activity。
  6. 但是,accept 仅目标账户可执行。并且只能接受一次。
  7. 因此,过期阈值是 86,400,000 ms。超时后自动退回源账户。
  8. 此外,mergeAccounts 要合并余额与 Activity。还要迁移全部引用。
  9. 总而言之,getBalance 需要历史账本。查询按 timeAt 回放或二分。

因此,推荐统一流水线。
每次请求先扫过期。
随后再执行业务。
最后写入历史快照。

统一流程图(System Design)

flowchart TD
A[收到请求] --> B[执行过期扫描]
B --> C{请求类型}
C --> D[createAccount]
C --> E[deposit/pay]
C --> F[transfer/accept]
C --> G[mergeAccounts]
C --> H[getBalance]
D --> I[更新当前状态]
E --> I
F --> I
G --> I
H --> J[按 timeAt 查历史]
I --> K[记录余额快照]
K --> L[返回结果]

此外,下面给出 Python 参考实现。
代码可用于口述,也可现场手写核心段。

from dataclasses import dataclass
from bisect import bisect_right
from typing import Optional


@dataclass
class Transfer:
    tid: str
    ts: int
    src: str
    dst: str
    amount: int
    accepted: bool = False
    expired: bool = False


class LedgerBank:
    EXPIRE_MS = 86_400_000

    def __init__(self) -> None:
        self.balance: dict[str, int] = {}
        self.activity: dict[str, int] = {}
        self.history: dict[str, list[tuple[int, int]]] = {}
        self.transfers: dict[str, Transfer] = {}
        self.merge_to: dict[str, tuple[int, str]] = {}
        self.used_ids: set[str] = set()
        self.next_tid = 1

    # 按时间解析账户归属,确保 merge 后历史查询语义一致
    def _resolve_at(self, account_id: str, t: int) -> Optional[str]:
        cur = account_id
        while cur in self.merge_to and self.merge_to[cur][0] <= t:
            cur = self.merge_to[cur][1]
        if cur in self.balance or cur in self.history:
            return cur
        return None

    def _record(self, ts: int, account_id: str) -> None:
        if account_id not in self.history:
            self.history[account_id] = []
        arr = self.history[account_id]
        val = self.balance[account_id]
        if arr and arr[-1][0] == ts:
            arr[-1] = (ts, val)
        else:
            arr.append((ts, val))

    # 统一过期扫描:所有对外接口入口都先调用
    def _expire(self, ts: int) -> None:
        for tr in self.transfers.values():
            if tr.accepted or tr.expired:
                continue
            if ts >= tr.ts + self.EXPIRE_MS:
                tr.expired = True
                if tr.src in self.balance:
                    self.balance[tr.src] += tr.amount
                    self._record(ts, tr.src)

    def createAccount(self, ts: int, account_id: str) -> bool:
        self._expire(ts)
        if account_id in self.used_ids:
            return False
        self.used_ids.add(account_id)
        self.balance[account_id] = 0
        self.activity[account_id] = 0
        self.history[account_id] = [(ts, 0)]
        return True

    def deposit(self, ts: int, account_id: str, amount: int) -> Optional[int]:
        self._expire(ts)
        acc = self._resolve_at(account_id, ts)
        if acc is None or acc not in self.balance:
            return None
        self.balance[acc] += amount
        self.activity[acc] += amount
        self._record(ts, acc)
        return self.balance[acc]

    def pay(self, ts: int, account_id: str, amount: int) -> Optional[int]:
        self._expire(ts)
        acc = self._resolve_at(account_id, ts)
        if acc is None or acc not in self.balance:
            return None
        if self.balance[acc] < amount:
            return None
        self.balance[acc] -= amount
        self.activity[acc] += amount
        self._record(ts, acc)
        return self.balance[acc]

    def topActivity(self, n: int) -> list[str]:
        ranked = sorted(self.activity.items(), key=lambda x: (-x[1], x[0]))
        return [f"{aid}({val})" for aid, val in ranked[:n]]

    def transfer(self, ts: int, source: str, target: str, amount: int) -> str:
        self._expire(ts)
        s = self._resolve_at(source, ts)
        d = self._resolve_at(target, ts)
        if s is None or d is None or s == d:
            return ""
        if s not in self.balance or d not in self.balance:
            return ""
        if self.balance[s] < amount:
            return ""

        # 创建转账时只冻结,不计 activity
        self.balance[s] -= amount
        self._record(ts, s)
        tid = f"txn{self.next_tid}"
        self.next_tid += 1
        self.transfers[tid] = Transfer(tid, ts, s, d, amount)
        return tid

    def accept(self, ts: int, account_id: str, transfer_id: str) -> bool:
        self._expire(ts)
        acc = self._resolve_at(account_id, ts)
        tr = self.transfers.get(transfer_id)
        if acc is None or tr is None:
            return False
        if tr.accepted or tr.expired:
            return False
        if ts >= tr.ts + self.EXPIRE_MS:
            return False
        if acc != tr.dst:
            return False

        tr.accepted = True
        self.balance[tr.dst] += tr.amount
        self.activity[tr.src] += tr.amount
        self.activity[tr.dst] += tr.amount
        self._record(ts, tr.dst)
        return True

    def mergeAccounts(self, ts: int, account_id1: str, account_id2: str) -> bool:
        self._expire(ts)
        a = self._resolve_at(account_id1, ts)
        b = self._resolve_at(account_id2, ts)
        if a is None or b is None or a == b:
            return False
        if a not in self.balance or b not in self.balance:
            return False

        self.balance[a] += self.balance[b]
        self.activity[a] += self.activity[b]
        self._record(ts, a)

        # 迁移所有未完成 transfer 的引用
        for tr in self.transfers.values():
            if tr.accepted or tr.expired:
                continue
            if tr.src == b:
                tr.src = a
            if tr.dst == b:
                tr.dst = a
            if tr.src == tr.dst:
                tr.expired = True
                self.balance[a] += tr.amount
                self._record(ts, a)

        del self.balance[b]
        del self.activity[b]
        self.merge_to[b] = (ts, a)
        return True

    def getBalance(self, ts: int, account_id: str, time_at: int) -> int:
        self._expire(ts)
        acc = self._resolve_at(account_id, time_at)
        if acc is None or acc not in self.history:
            return -1
        arr = self.history[acc]
        idx = bisect_right(arr, (time_at, 10**18)) - 1
        return arr[idx][1] if idx >= 0 else -1

因此,这份实现有四个关键点。
第一,所有入口先调用 _expire
第二,transfer 创建时只扣源账户。
第三,accept 成功才计双方 Activity。
第四,history 仅记录余额快照。

此外,复杂度也要能说清。
普通查询多为 O(1)
topActivityO(A log A)
过期扫描是 O(T)
如果要优化,可用最小堆管理过期时间。
这正是 Meta OA 面经 2026 的标准解法。

专家备考策略与高频考点:Meta OA 面经 2026

首先,Meta OA 面经 2026 的核心是一致性。
因此,你开场要先讲四类状态。
分别是账户、转账、Activity、历史快照。
这样面试官更容易认可你的方案。

核心考点(BQ)

  • 首先,你是否能定义清晰返回语义。
  • 其次,你是否能保证扣款原子性。
  • 此外,你是否能统一过期触发点。
  • 与此同时,你是否能说明排序稳定性。
  • 但是,你是否能处理合并后的引用迁移。
  • 总而言之,你是否能解释历史查询语义。

STAR 应对策略(BQ)

  • S:首先,描述旧实现问题。比如过期逻辑分散。
  • T:其次,明确目标。比如统一扫描与统一记账。
  • A:因此,说明动作。先建状态机,再封装 _expire
  • R:最后,量化结果。边界用例通过,复杂度清晰。

此外,建议准备三组测试。
第一组测重复创建与空返回。
第二组测转账超时与自动退回。
第三组测合并后 getBalance 语义。
这能覆盖 Meta OA 面经 2026 高频追问。

总结与行动号召(CTA)

总而言之,Meta OA 面经 2026 难在语义统一。
其次,代码量并不大。
现在就做一次 45 分钟实战。
并且按上面清单逐条复盘。