← 返回博客列表 TikTok SDE NG 三轮复盘:数组修复 + 树平均距离 + 嵌套迭代器 + 异位词
TikTok

TikTok SDE NG 三轮复盘:数组修复 + 树平均距离 + 嵌套迭代器 + 异位词

2026-06-10

这波 TikTok SDE NG 面试一共三轮,整体偏硬核。前两轮都是纯 coding,每轮两道算法题,时间卡得比较紧,考察重点在思路清晰度代码完整性;题型以中高频算法为主,需要对复杂度和边界比较敏感。第三轮是 HM 面,从简历深挖项目经历,重点问 infra 背景与系统设计思路。下面逐题复盘。

一、第一轮 Coding

Q1:最多改一个元素,判断数组是否有序

题目:在允许最多修改数组一个元素的条件下,这个数组能否变成非递减有序?

从前往后遍历,找到第一个违反非递减的位置 i(即 nums[i] < nums[i-1])。此时有两种修复方式:把 nums[i-1] 调小到 nums[i],或把 nums[i] 调大到 nums[i-1]。选哪种取决于 nums[i-2]

def check_possibility(nums) -> bool:
    changed = False
    for i in range(1, len(nums)):
        if nums[i] < nums[i - 1]:
            if changed:                 # 已经改过一次,第二次违反 -> 失败
                return False
            changed = True
            # 优先把 nums[i-1] 压到 nums[i](不破坏更前面的序)
            if i >= 2 and nums[i - 2] > nums[i]:
                nums[i] = nums[i - 1]   # 只能抬高 nums[i]
            else:
                nums[i - 1] = nums[i]
    return True

时间 O(n)、空间 O(1)。关键是贪心选哪个改,不要无脑改后面那个。

Q2:树中到其他节点平均距离最小的节点

题目:找到树中「到其他所有节点平均距离最小」的节点,一条边算 1,要求 O(n)。

这是经典换根 DP(rerooting):先一次 DFS 求出根到所有节点的距离和 sum0 与每棵子树大小;再一次 DFS 换根,父节点答案推子节点:ans[child] = ans[parent] + (n - 2*size[child])。距离和最小的节点即答案。

def min_avg_distance(n, edges):
    g = [[] for _ in range(n)]
    for u, v in edges:
        g[u].append(v); g[v].append(u)
    size = [1] * n
    ans = [0] * n

    def dfs1(u, p, depth):
        ans[0] += depth
        for w in g[u]:
            if w != p:
                dfs1(w, u, depth + 1)
                size[u] += size[w]

    def dfs2(u, p):
        for w in g[u]:
            if w != p:
                ans[w] = ans[u] + n - 2 * size[w]
                dfs2(w, u)

    dfs1(0, -1, 0)
    dfs2(0, -1)
    return ans.index(min(ans))

两次 DFS 共 O(n),避免对每个节点单独 BFS 的 O(n²)。

二、第二轮 Coding

面试官先 2 分钟闲聊(问最近项目里怎么优化数据库查询性能),然后直接进编码。

Q1:嵌套整数列表迭代器

题目:给定嵌套整数列表(元素是整数或嵌套列表),实现迭代器按顺序遍历所有整数,自己定义数据结构并实现 next()hasNext()

逆序压入元素,hasNext() 时循环展开列表,直到栈顶是整数:

class NestedIterator:
    def __init__(self, nestedList):
        # 逆序压栈,栈顶始终是下一个待处理元素
        self.stack = nestedList[::-1]

    def next(self) -> int:
        # hasNext() 保证栈顶是整数,直接弹出
        return self.stack.pop()

    def hasNext(self) -> bool:
        while self.stack:
            top = self.stack[-1]
            if isinstance(top, int):
                return True
            # 栈顶是列表:弹出并逆序压回其内容
            self.stack.extend(self.stack.pop()[::-1])
        return False

面试官追问「为什么 next() 是摊还 O(1)」:每个元素最多入栈、出栈各一次,总操作量与元素数线性相关。记得覆盖「空嵌套列表」「多层嵌套」用例。

Q2:字母异位词分组(优于排序)

题目:将字母异位词分组,要求优于 O(nk log k)(k 为字符串最大长度)。

常规解法是排序字符串当 key(O(k log k)),但面试官要优化。用长度 26 的计数数组转 tuple 当 key,每个字符串处理是 O(k):

from collections import defaultdict

def group_anagrams(strs):
    groups = defaultdict(list)
    for s in strs:
        count = [0] * 26              # "aab..." -> [2,1,0,...]
        for ch in s:
            count[ord(ch) - ord('a')] += 1
        groups[tuple(count)].append(s)   # tuple 可哈希,当 key
    return list(groups.values())

面试官提示「能用质数乘积当 key 吗」,可以补充:质数乘积可能溢出,计数数组更安全,也更贴合生产场景。总复杂度 O(nk)。

三、第三轮 HM 面

全程围绕简历展开,更关注沟通和成长性。先自我介绍,再挑项目提问,重点问:

  1. 最有挑战性的项目(infra / 系统设计选型与落地)。
  2. 如何与队友协作。
  3. 遇到突发情况如何处理——可分享一段实习经历:因为什么导致失败、最后怎么解决并避免再犯,回答要能「圆回来」,技术细节也要到位。

这轮通常不考 coding,是「正常聊天」式,从你的表达决定是否合适。

四、总结

TikTok SDE NG 三轮:前两轮纯 coding 考思路清晰 + 代码完整 + 边界敏感(数组贪心、换根 DP、栈迭代器、计数 key),第三轮 HM 看沟通与成长。难点不在单题,而在快节奏下两题连做还要讲清复杂度


FAQ

Q1:TikTok SDE NG 几轮?

三轮:前两轮纯 coding(每轮两题,时间紧),第三轮 HM 简历深挖 + infra/系统设计 + 行为题。

Q2:异位词分组为什么不用排序?

排序 key 是 O(k log k),面试官要求优于此。用长度 26 计数数组转 tuple 当 key,每串 O(k),总 O(nk),且避免质数乘积溢出风险。

Q3:嵌套迭代器怎么答得稳?

用栈逆序压入,hasNext() 循环展开列表直到栈顶是整数,next() 直接弹出。要能解释「每元素最多进出栈各一次」=> 摊还 O(1),并覆盖空列表与多层嵌套。

Q4:怎么应对两题连做的快节奏?

先 clarify 输入格式再落笔、边写边覆盖边界、主动讲复杂度。如需 TikTok 快节奏 coding 轮的限时陪练,或 VO代面 / VO辅助 的实时对接,可发岗位 JD 先做题型预测。


正在准备 TikTok 面试?

oavoservice 提供 TikTok SDE 全流程陪练:双题连做限时模拟、换根 DP/栈迭代器/计数 key 等高频题演练、HM 简历深挖与 infra 系统设计问答,也支持 VO代面 / VO辅助 的实时对接。教练含前大厂资深工程师,熟悉 TikTok「思路清晰 + 代码完整」的评分风格。

立即添加微信 Coding0201获取 TikTok 真题与陪练

联系方式