← Back to blog ByteDance OA 2026 Top Questions & Interviewer Insights from Past Candidates
ByteDance

ByteDance OA 2026 Top Questions & Interviewer Insights from Past Candidates

2026-05-18

ByteDance's 2026 OA bundles TikTok, Douyin, Lark, Doubao, CapCut, Volcano Engine and other product lines under the same CodeSignal Industry Coding question bank — meaning whether you applied for a North America SDE Intern slot or a Singapore DataEng role, the question type distribution you hit is highly homogeneous. However, the OA setters and the onsite interviewers come from different BUs, so even with identical question text, "the optimal solution the interviewer is mentally expecting" gets micro-tuned per BU.

This post does not repeat the "questions + solutions" checklist (a dedicated retro post already exists). Instead, standing on the past-candidate and review side, it walks through the 5 Top question categories, giving for each: category overview → high-frequency real question + full Python solution → interviewer follow-up angles → scoring rubric. At the end you'll find BU differences, score distribution, and FAQ.


ByteDance OA Overview

Dimension Details
Platform CodeSignal Industry Coding (NA / Singapore / UK); domestic uses Nowcoder / internal OJ
Duration 70 minutes (NA), 100–120 minutes (domestic)
Volume 4 questions (CodeSignal) / 3–4 questions (domestic)
Difficulty LC Easy ~ Medium (occasional Medium-Hard closer)
Scoring Partial test-case credit, not all-or-nothing; 800 / 600 are common cutoffs
Anti-cheat Tab-switching is logged; from 2026, random webcam snapshots are added (select BUs)

Key tip: NA and Singapore share ~70% of the question bank, and within the same week the repeat rate hits 40%, so 1point3acres weekly threads are extremely valuable for OA.


Top Category 1: Dynamic Programming (DP, ~28%)

Category overview

ByteDance OA DP leans toward 1D / 2D state, with the focus on the speed of "recognize state + write transition". Common wrappers: path counting, string matching, optimal partitioning, knapsack variants. Tree DP and bitmask DP almost never appear, but from 2026-Q1 we are starting to see 2D DP with constraints (e.g., "number of grid paths with at most k ones per row").

High-frequency real question: Maximum square with blockers

Given a 0/1 grid, find the largest square area made entirely of 1s; cells marked 2 mean "any submatrix containing them is invalid".

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

Time complexity: O(R·C), space O(R·C).

Interviewer follow-up angles

  1. Space optimization: Can you compress to an O(C) 1D array? (must-answer)
  2. Blocker semantics change: If 2 becomes "semi-transparent" — allowed inside but area gets multiplied by 0.5 — how would you adjust? (state extensibility)
  3. Very large n×m (10⁵ × 10⁵): DP is insufficient; how would you approximate? (mention blocking / sampling)

Scoring rubric

Performance Score
Writes naive O(R²C²); fails large test cases < 40%
Writes O(RC) DP, AC on most cases 70–85%
Adds space optimization + clear edge cases (empty grid / single row) 90%+

Top Category 2: Sliding Window (~22%)

Category overview

ByteDance sliding window questions "look like LC Easy but stack 3 layers of conditions" — e.g., "longest substring such that a appears at least k times and b appears at most m times". Core check: did you use while shrink + Counter maintenance, instead of nested-for brute force?

High-frequency real question: Longest substring with at most K distinct chars (weighted)

Each character carries a weight; the substring must have "distinct-char count ≤ K"; output the maximum weight sum for a qualifying substring.

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

Time complexity: O(n), space O(K).

Interviewer follow-up angles

  1. Negative weights: when weights can be negative, monotonic shrink breaks — how to fix? (need prefix sum + monotonic deque)
  2. K very large (≈ alphabet size): the window degenerates to the full string; is it still meaningful?
  3. Streaming input: if s is an infinite stream, how would you maintain incrementally?

Scoring rubric

Performance Score
Brute force O(n²) 50–60%
Standard sliding window O(n) 80–90%
Adds "negative weights" note or answers a follow-up 95%+

Top Category 3: Graph / BFS (~20%)

Category overview

ByteDance graph OA leans toward grid BFS / multi-source BFS / topological sort; shortest path is rarely tested (Dijkstra appears in < 5%). The focus is "multiple sources diffusing simultaneously" — TikTok's "viral spread" / "recommendation chain" wrappers show up especially often.

High-frequency real question: Multi-source BFS — distance to nearest "supply point"

Given an m×n grid, 1 is an obstacle, 2 is a supply point (multiple), 0 is empty space. Compute the shortest distance from every empty cell to its nearest supply point; unreachable cells are filled with -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]

Time complexity: O(R·C), space O(R·C).

Interviewer follow-up angles

  1. Weighted edges: if traversal cost differs per empty cell, BFS isn't enough — would you switch to 0-1 BFS or Dijkstra?
  2. Dynamic sources: supply points are added/removed dynamically; re-running BFS is too slow — how to maintain incrementally?
  3. k-nearest: required is the sum of distances to the "k nearest supply points" for each empty cell.

Scoring rubric

Performance Score
Single-source BFS run V
Single-pass multi-source BFS 85–95%
Mentions 0-1 BFS or incremental maintenance 95%+

Top Category 4: String Processing / Parsing (~18%)

Category overview

ByteDance "string questions" rarely test KMP / Z-algo; 90% are simulation + state machine. Common wrappers: log parsing, nested brackets, version-number comparison, emoji / Unicode splitting (this is a TikTok specialty due to multilingual product needs).

High-frequency real question: Nested curly-brace variable substitution

Input "Hello {name}, your balance is {amount} {currency}" plus a dict; output the substituted string. Supports nesting: {a_{idx}} should first resolve the inner {idx} and then the outer.

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

Time complexity: worst O(n²) (nesting depth = O(n)), typical O(n).

Interviewer follow-up angles

  1. Variable value contains {: will the substitution trigger a second pass of parsing? (edge-case trap)
  2. Circular references: {a}{b}, {b}{a} — how do you detect and raise an error?
  3. i18n: if the template contains emoji and CJK, should the slicing be done by grapheme rather than by byte?

Scoring rubric

Performance Score
Single-layer substitution correct 60%
Nested parsing + missing-key fallback 80%
Handles circular references / Unicode 95%+

Top Category 5: Simulation + Heap / Greedy (~12%)

Category overview

ByteDance "simulation problems" are characterized by long descriptions, many states, business-flavored — battery scheduling, order matching, live-stream danmaku rate limiting, ad-bidding queues. The exam point is not the algorithm itself but whether you can translate the problem statement into a clean state machine. Average length is 600+ words for this category; many candidates get stuck here not because they can't code it, but because they didn't fully parse the problem.

High-frequency real question: Streaming order matching (simplified)

A stream of buy / sell orders arrives; matching rules:

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

Time complexity: O(n log n), space O(n).

Interviewer follow-up angles

  1. Tie-breaking at equal price: if the rule changes to "prioritize larger quantity", how do you adjust the heap key?
  2. Cancellation: users can send "cancel order id" — heap doesn't support random removal; what data structure would you use? (lazy deletion / SortedList)
  3. Fairness: if 1000 orders arrive simultaneously, is your implementation fair? (batch processing vs FIFO)

Scoring rubric

Performance Score
Sort-based simulation O(n²) 40–55% (large cases TLE)
Two-heap O(n log n) 80–90%
Handles cancellation + partial fills + explains lazy deletion 95%+

OA Differences Across Roles

ByteDance has many internal BUs; OA question text is shared but the topic weights differ. Past-candidate observations:

Role / BU Heavy-weight categories Light categories Duration
TikTok SDE (NA) Sliding window + graph BFS + string DP (~1 question) 70 min
Douyin SDE (domestic) DP + simulation + data structures Strings relatively rare 100 min
Lark SDE Simulation (collaboration conflicts) + graph Sliding window less common 90 min
Data Engineer SQL-to-Python + streaming aggregation Algorithm — only 1 question 90 min
ML / Algorithm Probability + math + DP Less simulation 90 min
CapCut / Video 2D DP + geometric simulation No SQL 70 min

Key observation: DataEng OAs frequently ask "write an aggregation in Python equivalent to a given SQL" — simpler than SDE, but the trap is NULL handling.


Real Score Distribution from Our Students

We collected feedback from 60+ students on the ByteDance CodeSignal OA during 2026-Q1:

Score band Student share Subsequent onsite rate
900–1000 (perfect) 8% ~95%
800–899 22% ~75%
700–799 31% ~50% (cutoff zone)
600–699 24% ~20%
< 600 15% ~5%

Key findings:

  1. 800 is the de-facto cutoff: in NA, TikTok / Lark new-grad onsite invitations basically start at 800;
  2. Getting partial cases on Q4 (last question) beats fully solving Q3 — score weights ramp up per question;
  3. 70% of students get blocked on time, not on difficulty: 80% claim "10 more minutes and I'd AC" — so pacing matters more than grinding hard problems;
  4. Second attempts gain ~150 points: after fully digesting mistakes from the prior OA, average gain is 150 (700 → 850).

FAQ

Q1: Can I just grind 1point3acres high-frequency to pass ByteDance OA?

Partly true. CodeSignal repeat rate is 30–40%, but from 2026-Q2 ByteDance has been injecting new questions more frequently, about 1–2 per week. So the "pure grinding" pass rate dropped from ~75% in 2025 to ~55% in 2026. Recommend grinding + timed mocks in parallel.

Q2: How soon after OA do I hear about onsite?

NA: 1–2 weeks; domestic: 3–7 days; Singapore: typically 2 weeks. If you score 850+ in the same week and your resume matches the BU, HR will reach out within 3 business days. If 14 days pass with no word, a proactive follow-up email beats waiting silently.

Q3: How strict is CodeSignal's anti-cheat?

Tab-switches are logged (not auto-fail, but visible to HR); from 2026 TikTok / Doubao add random webcam snapshots, once every 5–10 minutes. Prohibited: second monitor, third-party IDE, other people in the room (multi-face triggers warnings). Do it in a clean environment, one shot.

Q4: Python or C++? TLE risk on ByteDance OA?

95% of questions won't TLE in Python — because ByteDance n caps usually at ≤ 10⁵. But streaming / simulation questions can still TLE if you overuse list.pop(0) or O(n²) string concatenation. Recommend: use collections.deque, avoid += for strings, use sys.stdin for input.

Q5: How long after failing OA can I reapply? Does cross-BU count as re-applying?

Official policy: 6-month cooldown. In practice: on the NA side, 3 months is enough to re-apply to the same BU (HR rarely enforces strictly); cross-BU does not count toward the cooldown at all — so failing TikTok and applying to Lark a month later is a common move. However: before going cross-BU, debrief the weaknesses of your previous OA; otherwise you're just changing the wrapper.


Preparing for ByteDance / TikTok / Lark / Doubao OA?

ByteDance 2026 OA question-bank turnover is accelerating; pure grinding isn't enough — the key is to fully connect "question category → interviewer follow-up → scoring rubric". We've collected this-week high-frequency questions across 6 ByteDance BUs in 2026, plus timed mocks, mistake debriefs, real-time OA assistance, and VO mock interviews.

Add WeChat Coding0201 now, get the ByteDance OA question bank.

Contact