ByteDance (TikTok, CapCut, Lark, Doubao, etc.) is hiring aggressively across US, Singapore, and UK hubs in 2026. Compared with 2025, ByteDance VO scoring has expanded from 3 axes to 5: algorithm and system design are now joined by "Chinese-English bilingual fluency" and "business intuition".
This article skips the OA section (we have a dedicated piece) and zooms into onsite — 10 recurring questions seen in Q1/Q2 2026 debriefs, with Python solutions and the "bonus points" your interviewer is actually grading for.
ByteDance VO 5-Axis Rubric
| Axis | Weight | Key Signals |
|---|---|---|
| 1. Algorithm / DS | 35% | Time complexity, coding speed, bug-free |
| 2. System Design | 25% | Trade-off articulation, horizontal scaling, bottleneck identification |
| 3. Behavioral | 15% | Conflict resolution, ownership |
| 4. Bilingual communication | 15% | Seamless CN-EN switching, terminology accuracy |
| 5. Business intuition | 10% | Articulate 1-2 TikTok / CapCut product decisions |
Why axes 4-5 were added in 2026: hiring managers reported that English-only candidates ran ~30% slower on cross-region collaboration. So now it's an explicit signal.
Question 1: Video Feed Recommendation Dedup
Problem
Build a feed-recommendation dedup module:
- User's last 7-day viewed set
seen(~10K) - Candidate stream (~100M)
- Return top 100 unseen IDs
- Constraints: QPS 100K, memory-bounded
Approach
Naive set lookups are O(1) but cost ~100MB per user. ByteDance uses Bloom Filter in production:
- 1% false positive tolerance
- ~10 bits per ID
- 10K IDs → 12.5KB
import hashlib
class BloomFilter:
def __init__(self, capacity, error_rate=0.01):
self.size = self._optimal_size(capacity, error_rate)
self.hash_count = self._optimal_hashes(capacity, self.size)
self.bits = bytearray(self.size // 8 + 1)
def _optimal_size(self, n, p):
import math
return int(-(n * math.log(p)) / (math.log(2) ** 2))
def _optimal_hashes(self, n, m):
import math
return max(1, int((m / n) * math.log(2)))
def _positions(self, item):
h1 = int(hashlib.md5(item.encode()).hexdigest(), 16)
h2 = int(hashlib.sha1(item.encode()).hexdigest(), 16)
return [(h1 + i * h2) % self.size for i in range(self.hash_count)]
def add(self, item):
for pos in self._positions(item):
self.bits[pos // 8] |= 1 << (pos % 8)
def __contains__(self, item):
return all(
self.bits[pos // 8] & (1 << (pos % 8))
for pos in self._positions(item)
)
def filter_top(candidates, seen_ids, k=100):
bf = BloomFilter(capacity=len(seen_ids))
for sid in seen_ids:
bf.add(sid)
result = []
for vid in candidates:
if vid not in bf:
result.append(vid)
if len(result) == k:
break
return result
Bonus: explicitly say "1% false positive means rare repeat exposure — preferable to cache-miss content gaps."
Question 2: Real-time Top-K (Hot Hashtag)
Problem
TikTok needs the hottest 100 hashtags over the last 24 hours. Event rate: ~1M events/sec.
Approach
Two-layer:
- Stream aggregation: Count-Min Sketch (approx counts)
- Top-K maintenance: Min-Heap (size = 100), batch-updated every second
from heapq import heappush, heappop
class HotHashtag:
def __init__(self, width=10000, depth=5, top_k=100):
self.width = width
self.depth = depth
self.cms = [[0] * width for _ in range(depth)]
self.heap = []
self.in_heap = set()
self.top_k = top_k
def _hash(self, item, i):
return hash((item, i)) % self.width
def add(self, hashtag):
for i in range(self.depth):
self.cms[i][self._hash(hashtag, i)] += 1
est = min(self.cms[i][self._hash(hashtag, i)] for i in range(self.depth))
if hashtag in self.in_heap:
pass
elif len(self.heap) < self.top_k:
heappush(self.heap, (est, hashtag))
self.in_heap.add(hashtag)
elif est > self.heap[0][0]:
_, old = heappop(self.heap)
self.in_heap.discard(old)
heappush(self.heap, (est, hashtag))
self.in_heap.add(hashtag)
def top(self):
return sorted(self.heap, reverse=True)
Bonus: explicitly mention "24-hour sliding window" requires CMS to decay — use sliding-window CMS or reset one bucket per hour.
Question 3: Comment Tree Collapse
Problem
Given [(parent_id, child_id, like_count)]:
- Display first 3 layers
- Collapse layer ≥ 4 with "view more"
- Each layer sorted by like_count desc
Approach
Standard DFS + level cap. ByteDance frequently asks for on-the-fly extension: "if like_count ties, sort by timestamp desc." This tests code extensibility.
from collections import defaultdict
def build_comment_tree(comments, max_depth=3):
children = defaultdict(list)
info = {}
roots = []
for parent_id, child_id, likes in comments:
info[child_id] = {"likes": likes, "id": child_id}
if parent_id is None:
roots.append(child_id)
else:
children[parent_id].append(child_id)
def dfs(node_id, depth):
if depth > max_depth:
return {"id": node_id, "collapsed": True}
kids = sorted(children[node_id], key=lambda c: -info[c]["likes"])
return {
"id": node_id,
"likes": info[node_id]["likes"],
"children": [dfs(c, depth + 1) for c in kids],
}
return [dfs(r, 1) for r in sorted(roots, key=lambda c: -info[c]["likes"])]
Time: O(n log n)
Questions 4-7: Algorithm Quick Reference
| # | Problem | Key Technique |
|---|---|---|
| 4 | Video duration bucketing | Bucket sort + prefix sum |
| 5 | User interest profile match | Jaccard + LSH |
| 6 | Push timing optimization (by timezone) | Offline cron + DAG scheduler |
| 7 | Live-comment debouncing | Sliding window + rate limit |
Question 8: System Design — Short-Video CDN Node Selection
Problem
Route global users to nearest CDN node for short-video requests:
- 50 global CDN nodes
- QPS 100M
- < 100ms route resolution
- Real-time node health feedback
Approach
Multi-layer:
- DNS: Anycast + GeoDNS, returns K=5 candidates
- Client SDK: Picks lowest-RTT among 5 via probe
- Backend coordination: CDN nodes push health to Coordinator → Coordinator pushes weighted RR table to DNS
Bonus:
- Mention bandwidth-aware routing (latency + remaining bandwidth)
- Cold-start cache warming (new videos go to single point, hot videos multi-replica)
- Cost optimization (off-peak concentration on fewer nodes)
Question 9: System Design — Real-Time Feed Ranking
Problem
After a user finishes a video, refresh recommendations within 100ms.
Key Design
- Online inference: Two-tower model, user tower updates embedding live
- Cache layer: Pre-ranked candidate pool in Redis
- Streaming: Kafka → Flink → Embedding Service
- Fallback: If real-time path TLE, fall back to batch recs
What HMs look for: "I'd run offline A/B first to verify the retention lift covers extra GPU cost."
Question 10: BQ — "Cross-team Conflict"
Most frequent ByteDance BQ. Structure:
- Conflict — cross-team misalignment
- Actions — concrete (RFC, PM 1:1, SVP doc), not "communicated"
- Result — quantifiable (latency -20%, retention +3%)
- Learning — generalizable lesson (new 2026 axis, 20% weight)
Learning must be generalizable. "I'll sync earlier next time" is empty. "I established a weekly cross-team standup that eliminated 60% of ad-hoc syncs" is real.
FAQ
Q1: Are overseas and domestic ByteDance interviews the same?
No. Domestic runs on BOSS Zhipin + Niuke + Lark Meet; overseas uses Greenhouse + CoderPad + Zoom. Domestic skews LC Hard, overseas LC Medium-Hard. Domestic has HC lock; overseas allows candidate-vs-candidate comparison.
Q2: TikTok vs other ByteDance BU interview differences?
| BU | Algo focus | Design focus | Chinese required |
|---|---|---|---|
| TikTok | Recommendation / Video | CDN / Feed | No |
| Lark | Collaboration / IM | Multi-edit / Realtime | No |
| CapCut | Video editing / FFmpeg | C++ perf | No |
| Doubao | LLM / Search | Inference | Yes (CN+EN) |
Non-Chinese speakers: Doubao and some TikTok Algo teams run standup and code review in Chinese.
Q3: How long from VO pass to offer?
Average 5-15 days. Overseas HC (called "Hiring Loop Closing") runs weekly. Team match delays add 1-2 weeks if you express preference mismatch.
Q4: 2026 comp ranges?
| Level | Base (US West) | Total Comp |
|---|---|---|
| L4 SDE | $160-180K | $240-280K |
| L5 SDE | $200-230K | $330-380K |
| L6 Senior | $240-280K | $400-470K |
| L7 Staff | $300-350K | $530-650K |
Note: ByteDance RSU is pre-IPO restricted shares, tradable on Forge/EquityZen with ±15% price volatility. Base + bonus cash is more stable.
Q5: How many onsite rounds?
Standard 5: 3× coding + 1× system design + 1× BQ. Senior+ adds 1× cross-functional (peer-level staff from outside the team).
Q6: How long is the cooldown if I fail?
6 months. Hack: switching BU at 4 months resets cooldown (e.g., TikTok onsite fail → apply Lark). Best practice: disclose proactively to avoid background-check surprises.
Preparing for ByteDance / TikTok / Lark / Doubao overseas roles?
The 2026 cycle adds bilingual fluency and business intuition to the rubric — pure LeetCode grinding is no longer enough. We've curated 2026 onsite question banks + system-design cheat sheets + BQ templates for all four major BUs, plus bilingual mock interviews.
Add WeChat Coding0201 or contact us.
Contact
Email: [email protected] Telegram: @OAVOProxy