字节跳动 2026 OA 把 TikTok、抖音、Lark、Doubao、CapCut、火山引擎等多个产品线统一在同一套 CodeSignal Industry Coding 题库——这意味着不论你投的是北美 SDE Intern 还是新加坡 DataEng,碰到的题型分布是高度同质的。但是,OA 出题人和 onsite 面试官来自不同 BU,因此即便题面一样,"面试官心里期待的最优解"会按 BU 微调。
本文不重复"题目+解法"清单(已有专门复盘文),而是站在过来人和 review 端梳理 5 大 Top 题型,逐题给出:题型简介 → 高频真题 + Python 完整解法 → 面试官追问角度 → 评分标准,文末附 BU 差异、分数分布与 FAQ。
ByteDance OA 概览
| 维度 | 详情 |
|---|---|
| 平台 | CodeSignal Industry Coding(北美 / 新加坡 / 英国),国内走牛客 / 内部 OJ |
| 时长 | 70 分钟(北美),100–120 分钟(国内) |
| 题量 | 4 题(CodeSignal)/ 3–4 题(国内) |
| 难度 | LC Easy ~ Medium(偶有 Medium-Hard 收尾题) |
| 评分 | 部分用例计分,不是全或无,800/600 是常见 cutoff |
| 反作弊 | 切屏会被记录;2026 起加入摄像头随机抓拍(部分 BU) |
关键提示:北美与新加坡共享题库约 70%,同一周内重复率高达 40%,因此"一亩三分地周报"在 OA 里非常值钱。
Top 题型 1:动态规划(DP,约 28%)
题型简介
字节 OA 的 DP 偏一维 / 二维状态,重点考察"识别状态 + 写出转移"的速度。常见包装:路径计数、字符串匹配、最优分段、背包变体。几乎不会出树形 DP 或状压 DP,但 2026-Q1 起开始出现带约束的二维 DP(如"每行至多 k 个 1 的网格路径数")。
高频真题:带障碍的最大正方形
给定一个 0/1 网格,找出仅由 1 构成的最大正方形面积;网格中标记为 2 的格子表示"任何包含它的子矩阵都无效"。
def max_square_with_blockers(grid):
R, C = len(grid), len(grid[0])
# 先按 blocker 标记不可用区域
blocked = [[False] * C for _ in range(R)]
for r in range(R):
for c in range(C):
if grid[r][c] == 2:
for dr in range(R):
for dc in range(C):
if dr <= r and dc <= c:
blocked[r][c] = True # 简化版
dp = [[0] * C for _ in range(R)]
best = 0
for r in range(R):
for c in range(C):
if grid[r][c] != 1 or blocked[r][c]:
continue
if r == 0 or c == 0:
dp[r][c] = 1
else:
dp[r][c] = min(dp[r-1][c], dp[r][c-1], dp[r-1][c-1]) + 1
best = max(best, dp[r][c])
return best * best
时间复杂度:O(R·C),空间 O(R·C)。
面试官追问角度
- 空间优化:能不能压成 O(C) 一维数组?(必答得出)
- blocker 语义改变:如果
2改成"半透明"——可以包含但面积乘 0.5 的话怎么改?(考察状态可扩展性) - n×m 极大时(10⁵ × 10⁵):DP 不够用,要怎么近似?(提到分块 / 抽样)
评分标准
| 表现 | 得分 |
|---|---|
| 写出朴素 O(R²C²) 也跑不过大用例 | < 40% |
| 写出 O(RC) DP,AC 大部分用例 | 70–85% |
| 加上空间优化 + 边界(空网格 / 单行)解释清楚 | 90%+ |
Top 题型 2:滑动窗口(约 22%)
题型简介
字节滑窗题"看起来像 LC Easy 但条件叠到 3 层"——比如"最长子串使得 a 至少出现 k 次且 b 不超过 m 次"。核心考察:你有没有用 while 收缩 + Counter 维护,而不是嵌套 for 暴力。
高频真题:含至多 K 类不同字符的最长子串(带权)
每个字符有权重,要求子串内"字符类别数 ≤ K",输出权重和最大的子串长度。
from collections import Counter
def longest_weighted_window(s, weights, K):
"""
s: 字符串
weights: dict, weights[c] 为字符 c 的权重
K: 允许的不同字符种类上限
返回: 满足条件的最大权重和
"""
cnt = Counter()
left = 0
cur_weight = 0
best = 0
for right, ch in enumerate(s):
cnt[ch] += 1
cur_weight += weights.get(ch, 0)
while len(cnt) > K:
lc = s[left]
cnt[lc] -= 1
cur_weight -= weights.get(lc, 0)
if cnt[lc] == 0:
del cnt[lc]
left += 1
best = max(best, cur_weight)
return best
时间复杂度:O(n),空间 O(K)。
面试官追问角度
- 权重可负:当 weight 可以为负数时,单调收缩失效——怎么改?(需要用前缀和 + 单调队列)
- K 极大(≈ alphabet size):滑窗会退化成全串,是否还有意义?
- 流式输入:如果 s 是无限流,怎么 incremental 维护?
评分标准
| 表现 | 得分 |
|---|---|
| 暴力 O(n²) | 50–60% |
| 标准滑窗 O(n) | 80–90% |
| 加上"权重可负"备注或回答追问 | 95%+ |
Top 题型 3:图论 / BFS(约 20%)
题型简介
字节图论 OA 偏网格 BFS / 多源 BFS / 拓扑排序,不太考最短路(Dijkstra 出现率 < 5%)。重点是"多个起点同时扩散"——TikTok 的"病毒传播""推荐链路"包装尤其多。
高频真题:多源 BFS——最近的"补给点"距离
给定 m×n 网格,1 表示障碍,2 表示补给点(多个),0 表示空地。求每个空地到最近补给点的最短距离;不可达填 -1。
from collections import deque
def nearest_supply(grid):
R, C = len(grid), len(grid[0])
INF = float("inf")
dist = [[INF] * C for _ in range(R)]
q = deque()
for r in range(R):
for c in range(C):
if grid[r][c] == 2:
dist[r][c] = 0
q.append((r, c))
while q:
r, c = q.popleft()
for dr, dc in ((1, 0), (-1, 0), (0, 1), (0, -1)):
nr, nc = r + dr, c + dc
if 0 <= nr < R and 0 <= nc < C and grid[nr][nc] != 1:
if dist[nr][nc] > dist[r][c] + 1:
dist[nr][nc] = dist[r][c] + 1
q.append((nr, nc))
return [[-1 if v == INF else v for v in row] for row in dist]
时间复杂度:O(R·C),空间 O(R·C)。
面试官追问角度
- 加权边:如果不同空地通行成本不同,BFS 不够用——你会换 0-1 BFS 还是 Dijkstra?
- 动态加点:补给点会动态增减,重新跑 BFS 太慢,怎么 incremental 维护?
- k-nearest:要求每个空地到"前 k 个最近补给点"的距离总和。
评分标准
| 表现 | 得分 |
|---|---|
| 单源 BFS 跑 | V |
| 多源 BFS 一次跑完 | 85–95% |
| 答出 0-1 BFS 或 incremental 维护 | 95%+ |
Top 题型 4:字符串处理 / 解析(约 18%)
题型简介
字节"字符串题"很少考 KMP / Z-algo,90% 是模拟 + 状态机。常见包装:日志解析、嵌套括号、版本号比较、表情符号 / Unicode 切分(这是 TikTok 特色,因为产品多语言)。
高频真题:嵌套花括号变量替换
输入 "Hello {name}, your balance is {amount} {currency}" 与一个 dict,输出替换后的字符串;支持嵌套:{a_{idx}} 应先替换内层 {idx} 再替换外层。
def render_template(tpl, ctx):
while "{" in tpl:
# 找最内层 {...}(不含嵌套)
start = -1
for i, ch in enumerate(tpl):
if ch == "{":
start = i
elif ch == "}" and start != -1:
key = tpl[start + 1:i]
if "{" in key:
# 还有嵌套,跳过这一对,从内部找
continue
value = str(ctx.get(key, ""))
tpl = tpl[:start] + value + tpl[i + 1:]
break
else:
break
return tpl
时间复杂度:最坏 O(n²)(嵌套深度 = O(n)),多数情况 O(n)。
面试官追问角度
- 变量值含
{:替换后会不会触发二次解析?(边界陷阱) - 循环引用:
{a}→{b},{b}→{a},怎么检测并报错? - 国际化(i18n):如果模板里有 emoji 和 CJK,字符切片要不要按字形而非 byte 切?
评分标准
| 表现 | 得分 |
|---|---|
| 单层替换写对 | 60% |
| 嵌套解析 + 缺 key 兜底 | 80% |
| 处理循环引用 / Unicode | 95%+ |
Top 题型 5:模拟 + 堆 / 贪心(约 12%)
题型简介
字节"模拟题"的特点是长描述、多状态、偏业务——电池调度、订单匹配、直播弹幕限流、广告竞价排队。考的不是算法本身,而是能不能把题干翻译成清晰的状态机。这一类题平均长度 600+ 词,很多人 OA 卡在这里不是因为不会写,而是没读懂。
高频真题:流式订单撮合(简化版)
收到一条买单 / 卖单流,撮合规则:
- 卖单价 ≤ 买单价 时撮合
- 同价格下按时间先到先匹配
- 输出每次撮合的成交价(取卖方挂单价)和数量
import heapq
def match_orders(orders):
"""
orders: [(t, side, price, qty)], side ∈ {"B","S"}
返回: [(成交时间, 成交价, 数量)]
"""
buys = [] # max-heap, 用 -price 实现
sells = [] # min-heap
trades = []
seq = 0
for t, side, price, qty in orders:
seq += 1
if side == "B":
heapq.heappush(buys, (-price, seq, qty))
else:
heapq.heappush(sells, (price, seq, qty))
# 尝试撮合
while buys and sells and -buys[0][0] >= sells[0][0]:
bp, bs, bq = buys[0]
sp, ss, sq = sells[0]
traded = min(bq, sq)
trades.append((t, sp, traded))
heapq.heappop(buys); heapq.heappop(sells)
if bq > traded:
heapq.heappush(buys, (bp, bs, bq - traded))
if sq > traded:
heapq.heappush(sells, (sp, ss, sq - traded))
return trades
时间复杂度:O(n log n),空间 O(n)。
面试官追问角度
- 价格相同时谁先成交:题目改成"按数量大优先",你怎么改 heap key?
- 撤单:用户可以发"取消订单 id"——heap 不支持随机删除,你用什么数据结构?(lazy deletion / SortedList)
- 公平性:如果同时来 1000 单,你的实现公平吗?(涉及 batch 处理 vs FIFO)
评分标准
| 表现 | 得分 |
|---|---|
| 用排序模拟 O(n²) | 40–55%(大用例 TLE) |
| 双堆 O(n log n) | 80–90% |
| 处理撤单 + 部分成交 + 解释 lazy del | 95%+ |
不同岗位 OA 差异
字节内部 BU 多,OA 题面共享但题目权重不同,过来人观察如下:
| 岗位 / BU | 强权重题型 | 偏弱题型 | 时长 |
|---|---|---|---|
| TikTok SDE(北美) | 滑窗 + 图 BFS + 字符串 | DP(约 1 题) | 70 分钟 |
| 抖音 SDE(国内) | DP + 模拟 + 数据结构 | 字符串相对少 | 100 分钟 |
| Lark / 飞书 SDE | 模拟(协同冲突)+ 图 | 滑窗较少 | 90 分钟 |
| Data Engineer | SQL 转 Python + 流式聚合 | 算法 1 题即可 | 90 分钟 |
| ML / Algorithm | 概率 + 数学题 + DP | 模拟较少 | 90 分钟 |
| CapCut / 视频 | 二维 DP + 几何模拟 | SQL 不出 | 70 分钟 |
关键观察:DataEng 岗位 OA 经常出"用 Python 写出与 SQL 等价的聚合"——比 SDE 简单但陷阱在 NULL 处理。
学员真实分数分布观察
我们整理了 2026-Q1 期间 60+ 学员反馈的 CodeSignal 字节 OA 分数:
| 分数段 | 学员占比 | 后续 onsite 概率 |
|---|---|---|
| 900–1000(满分) | 8% | ~95% |
| 800–899 | 22% | ~75% |
| 700–799 | 31% | ~50%(卡线) |
| 600–699 | 24% | ~20% |
| < 600 | 15% | ~5% |
关键发现:
- 800 分是隐性 cutoff:北美 TikTok / Lark 校招的 onsite 邀请基本从 800 起步;
- Q4(最后一题)拿到部分用例比 Q3 全做对更划算——分数权重逐题递增;
- 70% 学员卡时间不卡题:80% 学员声称"再多 10 分钟就 AC"——所以节奏管理比刷难题更重要;
- 二刷的提升幅度 ~150 分:吃透前一次 OA 的错点后再做,平均涨 150 分(从 700 → 850)。
FAQ
Q1:字节 OA 是不是"刷一亩三分地高频题就能过"?
部分正确。CodeSignal 题库重复率 30–40%,但 2026-Q2 起字节加大了"新题注入"频率,每周大约换 1–2 道。所以"完全靠刷"的学员通过率从 2025 的 75% 降到 2026 的 55% 左右。建议刷题 + 模拟限时同步进行。
Q2:OA 之后多久能收到 onsite 通知?
北美:1–2 周;国内:3–7 天;新加坡:通常 2 周。如果 OA 当周拿到 850+ 且简历匹配 BU,HR 会在 3 个工作日内主动 reach out。如果 14 天没消息,主动发邮件 follow-up 比干等更有效。
Q3:CodeSignal 的反作弊到什么程度?
切屏会被记录(不是直接挂,但 HR 可见);2026 起 TikTok / Doubao 加入摄像头随机抓拍,每隔 5–10 分钟一次。禁止行为:开第二个屏幕、第三方 IDE、有人在房间内(多人脸触发警告)。建议在干净环境一次性完成。
Q4:用 Python 还是 C++?字节 OA TLE 风险大吗?
95% 题目 Python 不会 TLE——因为字节的 n 上限通常 ≤ 10⁵。但流式题 / 模拟题如果用了过多 list.pop(0) 或字符串拼接 O(n²),仍可能 TLE。建议:用 collections.deque、避免 += 拼字符串、用 sys.stdin 读输入。
Q5:挂了 OA 多久能再投?跨 BU 算重投吗?
官方政策:6 个月冷冻期。实操:北美侧 3 个月即可重投同一 BU(HR 通常不严查),跨 BU 完全不计入冷冻——所以 TikTok 挂了 1 个月后投 Lark 是常见操作。但建议:跨 BU 之前先复盘上一次 OA 的薄弱点,否则换汤不换药。
正在准备 ByteDance / TikTok / Lark / Doubao OA?
字节 2026 OA 题库变化加速,单纯刷题已经不够——关键是把"题型 → 面试官追问 → 评分标准"链路理清楚。我们整理了 2026 当周字节系 6 大 BU 的高频题、限时模拟、错点复盘,并提供 OA 实时辅助 + VO mock interview。
立即添加微信 Coding0201,获取字节 OA 真题包。
联系方式
Email: [email protected]
Telegram: @OAVOProxy