Google SWE Intern VO 面经:两轮 Coding,Follow-up 考察 BFS 状态

这两天抽空整理了一组 Google SWE Intern VO 面经,一共两轮,都是 Coding。题目本身不算特别偏,主要考察 BFS 和二叉树遍历,但面试官在基础问题上继续增加条件后,对状态设计和边界处理的要求也会随之提高。

第一轮是二维网格最短路径,需要处理障碍物消除;第二轮是二叉树中距离目标节点恰好为 K 的节点,重点在于如何利用 parent 关系将树转换为可以双向遍历的结构。两道题都有 Follow-up,准备 Google SWE Intern 面试时,可以重点练习基础解法的变形。

第一轮:Coding|二维网格最短路径

题目描述

给定一个二维网格 grid,其中 0 表示可以通行的空格,1 表示障碍物。需要从左上角出发,到达右下角,每次只能向上、下、左、右四个方向移动。

最多可以消除一个障碍物,求从起点到终点的最短步数。如果无法到达终点,返回 -1。

解题思路

这道题可以使用 BFS(Breadth-First Search) 求最短路径。由于每次移动的代价相同,BFS 可以按距离从小到大的顺序搜索,第一次到达终点时,就能得到最短步数。

普通的网格 BFS 通常只需要记录当前位置,但这道题还需要考虑障碍物消除机会是否已经使用。

例如,同一个格子可能通过两种不同的状态到达:

  • 还没有消除过障碍物,后续仍然可以消除一次。

  • 已经消除过障碍物,后续不能再穿过障碍物。

虽然坐标相同,但这两种状态的后续选择并不相同,因此不能只根据 (row, col) 判断是否访问过。

具体实现时,可以将状态记录为 (row, col, used),其中 used 表示是否已经使用障碍物消除机会。将起点加入队列后,每次取出一个状态,依次检查上下左右四个相邻位置:

  1. 如果相邻位置超出网格范围,则跳过。

  2. 如果目标位置是空格,可以直接移动。

  3. 如果目标位置是障碍物,需要检查消除机会是否已经使用;未使用时才能消除并继续移动。

  4. 对每个尚未访问过的合法状态进行标记,并加入队列。

按照 BFS 的层级顺序搜索,第一次到达右下角时即可返回最短步数。如果所有状态都搜索完毕仍未到达终点,则返回 -1。

时间复杂度: O(MN)。

空间复杂度: O(MN)。

这里的复杂度建立在最多消除一次障碍物的前提下,每个格子最多对应两种状态。

Follow-up:如果最多可以消除 K 个障碍物呢?

当障碍物消除次数从 1 次扩展到 K 次时,原来的 BFS 思路仍然适用,但状态需要进一步扩展。

可以将状态记录为 (row, col, remainingK),其中 remainingK 表示当前还剩多少次障碍物消除机会。

每次移动时,如果下一个位置是空格,剩余次数保持不变;如果是障碍物,则需要判断 remainingK 是否大于 0。只有剩余次数足够时,才能消除障碍物并继续搜索,同时将剩余次数减 1。

这里的关键仍然是 状态去重。如果只用坐标记录访问情况,就可能把一个仍然保留多次消除机会的状态,与一个已经消耗完机会的状态混为一谈,导致遗漏更优路径。

一种直接的实现方式是记录每个 (row, col, remainingK) 是否访问过。这样可以保证不同剩余次数对应的状态不会互相覆盖。

在这种实现下,时间复杂度和空间复杂度均为 O(MNK),其中 K 表示障碍物消除次数上限;如果将起始剩余次数也计入状态数量,更严格地说是 O(MN(K+1))。

第二轮:Coding|二叉树中距离目标 K 的节点

题目描述

给定一棵二叉树、一个目标节点 target 和一个整数 K,返回所有与目标节点距离恰好为 K 的节点。

这里的距离指两个节点之间经过的边数。例如,距离目标节点一条边的节点,包括它的左孩子、右孩子,以及可能存在的父节点。

解题思路

这道题可以使用 BFS + Parent Mapping 解决。

二叉树通常只能直接从父节点访问左右孩子,但题目要求查找目标节点周围、距离为 K 的所有节点。如果只向下遍历,就无法访问目标节点的祖先,以及祖先的其他子树。

因此,可以先遍历整棵树,建立每个节点与其父节点之间的映射关系。之后,从 target 开始执行 BFS,将每个节点的左孩子、右孩子和父节点都视为相邻节点。

具体步骤如下:

  1. 建立 Parent Mapping。 遍历二叉树,记录每个节点对应的父节点。

  2. 初始化 BFS。 将目标节点 target 加入队列,并使用 visited 集合记录已访问的节点。

  3. 逐层搜索。 每次处理当前层的所有节点,将它们的左孩子、右孩子和父节点加入下一层,但需要跳过已经访问过的节点。

  4. 收集第 K 层节点。 当 BFS 到达距离目标节点恰好为 K 的那一层时,该层所有节点就是答案。

这里需要特别注意 visited 的使用。因为建立父节点映射后,树的遍历方向不再局限于从上到下。例如,从目标节点移动到父节点后,再访问其孩子时,就可能重新回到之前经过的节点。如果没有访问记录,就可能重复搜索,甚至造成循环。

时间复杂度: O(N)。

空间复杂度: O(N)。

其中 N 为二叉树的节点数量。建立父节点映射和 BFS 搜索最坏情况下都需要线性时间与空间。

Follow-up:如果需要对同一棵树反复查询不同目标节点呢?

如果每次查询都重新遍历整棵树来建立 parent 映射,会产生重复开销。

更直接的优化方法是:在多次查询开始之前,先预处理整棵树的 Parent Mapping 。后续每次给定新的 target 和 K 时,就可以直接从目标节点开始 BFS,不必重新建立父节点关系。

这种方法适合树结构保持不变、需要处理多次查询的场景。

如果查询次数非常多,还可以进一步根据实际需求考虑更复杂的预处理方案,例如利用树的结构信息优化特定距离查询。但具体采用哪种方案,需要结合 K 的取值范围、查询次数,以及是否需要返回所有符合条件的节点来判断。

Google SWE Intern VO 复盘:Follow-up 才是重点

这两道题分别对应网格搜索和二叉树遍历,但核心考点有一定共通性:如何定义搜索状态,以及在状态发生变化后,如何正确处理访问记录。

第一题的难点在于障碍物消除次数会影响后续路径选择。坐标相同,不代表两个状态完全相同。Follow-up 将消除次数扩展为 K 后,还需要同步调整状态定义、访问记录和复杂度分析。

第二题的难点在于如何把原本只能向下遍历的二叉树转换成可以双向搜索的结构。建立 parent 映射后,必须使用 visited 防止重复访问;如果需要重复查询,则可以通过预处理减少不必要的工作。

准备 Google SWE Intern VO 时,建议不要只停留在基础解法。写完代码后,可以继续问自己几个问题:

  • 状态是否完整? 是否有其他信息会影响后续决策?

  • 去重逻辑是否正确? 两个位置相同的状态,是否真的可以视为同一个状态?

  • Follow-up 改变条件后,需要修改哪些部分? 除了核心算法,状态表示、边界处理和复杂度是否也需要调整?

  • 是否存在重复计算? 如果输入结构不变但查询次数增加,哪些信息可以提前预处理?

Google SWE Intern 的 Coding 面试不仅需要找到可行解法,也需要在面试官增加条件后,解释清楚原有思路为什么成立、哪些地方需要调整,以及新的复杂度是多少。

如果正在准备 Google SWE Intern VO,可以重点复习 BFS、树遍历、图搜索和常见的状态设计问题,同时练习在 Follow-up 中逐步修改已有解法。

相关推荐
琳达爱分享1 小时前
从单机令牌桶到集群限流:一次配额超发的复盘
后端·算法
range2 小时前
带TTL的LRU缓存的实现-字节手撕-26/10/19
算法
糖果豆豆2 小时前
n log n 到底从哪来?排序下界、2-SAT 与 3-SAT、停机问题,卡的是同一件事
算法·架构
地平线开发者2 小时前
【玩转 征程6 算法工具链:PTQ 工具篇】hb_verifier
算法·自动驾驶
171320330计算机毕设编程2 小时前
计算机毕业设计 基于springboot+vue的在线观鸟视频播放网站 LW PPT
java·大数据·vue.js·spring boot·算法·课程设计
himobrinehacken2 小时前
位运算揭秘:左右移与符号位陷阱
c语言·c++·算法·安全
INGNIGHT3 小时前
815 · 课程表IV(dfs)
算法·深度优先
Pniubi3 小时前
力扣146.LRU缓存机制
算法·leetcode·缓存
云上工程笔记3 小时前
2026年7B到67B模型训练与推理GPU配置评测:LoRA、量化与全量微调对比
人工智能·算法·机器学习