Google SWE 面经(2024 New Grad)
岗位:Software Engineer, New Grad(Mountain View)
背景:美硕 CS Top 30,一段 Google 暑期实习(return offer 面试)
结果: L4 offer(New Grad 拿 L4 比较少见,因为实习期间表现突出)
时间线:暑期实习 5–8 月 → 9.1 启动 return process → 9.15 HC 面 → 9.30 Hiring Committee 通过 → 10.15 team match → 11.1 offer
面试流程概览
Google SWE 面试一般包含:
- Phone Screen / OA(New Grad 通常是两道算法题)
- Virtual Onsite(4–5 轮,每轮 45-60min):
- 2 轮算法(Data Structures & Algorithms)
- 1 轮系统设计(System Design)
- 1 轮行为面试(Googleness / Leadership)
- **Hiring Committee(HC)**审核所有面试反馈
- Team Match(双向选择,可能持续数周)
我的面试因为是 return offer process,跳过了 Phone Screen,直接 onsite。
Onsite Round 1:算法(L4 难度)
面试官是一位在 Google 工作 10 年的 Staff Engineer,极其温和但追问很深入。
题目:岛屿计数 + 变体
LeetCode 200. 岛屿数量 的扩展版本。
原题很简单,DFS/BFS 即可。变体是:如果网格非常大($10^9 \times 10^9$),且岛屿坐标以 稀疏列表 形式给出(只给出是陆地 (x, y) 的坐标),如何高效求解?
from collections import defaultdict
def numIslandsSparse(land_coords):
"""
land_coords: List[Tuple[int, int]] - 只包含陆地坐标
"""
land_set = set(land_coords)
visited = set()
islands = 0
def neighbors(x, y):
for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
yield x + dx, y + dy
for coord in land_coords:
if coord in visited:
continue
# BFS for this island
queue = [coord]
visited.add(coord)
while queue:
x, y = queue.pop(0)
for nx, ny in neighbors(x, y):
nxt = (nx, ny)
if nxt in land_set and nxt not in visited:
visited.add(nxt)
queue.append(nxt)
islands += 1
return islands
追问:
- 时间复杂度? $O(L)$,L 是陆地坐标数,因为每个陆地只被访问一次。
- 空间复杂度? $O(L)$,集合存储。
- 如果 L 是 10 亿呢? 讨论 External Memory Algorithm,可能需要 MapReduce(因为无法单机内存存储)。
- 如何用 MapReduce 实现?
- Map:每个节点输出
(coord, label)和(coord, neighbor_label) - Reduce:通过并查集(Union-Find)合并连通分量
- 多轮迭代直到稳定
- Map:每个节点输出
Onsite Round 2:算法(优化)
面试官是 L5 的 Senior Engineer,题目是经典题的优化版本。
题目:搜索旋转排序数组 II
LeetCode 81. 搜索旋转排序数组 II(含重复元素)。
要求:最坏情况 $O(n)$ 无法避免,但平均情况尽量做到 $O(\log n)$。
from typing import List
def search(nums: List[int], target: int) -> bool:
left, right = 0, len(nums) - 1
while left <= right:
mid = (left + right) // 2
if nums[mid] == target:
return True
# 处理重复元素的情况
if nums[left] == nums[mid] == nums[right]:
left += 1
right -= 1
continue
# 哪一半是有序的?
if nums[left] <= nums[mid]: # 左半有序
if nums[left] <= target < nums[mid]:
right = mid - 1
else:
left = mid + 1
else: # 右半有序
if nums[mid] < target <= nums[right]:
left = mid + 1
else:
right = mid - 1
return False
追问:
- 如果数组没有重复元素,时间复杂度是什么?严格 $O(\log n)$
- 去除重复元素需要额外空间吗?不,原地就行。
- 你能把这个改写成递归形式吗?(现场改了,但其实和迭代等价)
关键观察:追问的重点不是"会不会做",而是"能不能清晰解释每一步的决策依据"。
Onsite Round 3:系统设计
题目:设计一个 URL 短链服务
要求:支持生成短 URL、根据短 URL 重定向到长 URL、支持自定义短码、统计访问次数。
我按 Google 的面试偏好 组织回答:
1. API Design
POST /api/v1/shorten
Body: { url: "https://example.com/...", custom_alias?: "abc123" }
Response: { short_url: "https://goo.gl/abc123", created_at: "..." }
GET /{short_code}
Response: 302 redirect to original URL
GET /api/v1/stats/{short_code}
Response: { clicks: 12345, countries: {...} }
2. Data Model
-- URLs 表
create table urls (
id bigint primary key,
short_code varchar(10) unique not null,
long_url text not null,
created_at timestamp default now(),
expires_at timestamp,
click_count bigint default 0
);
-- Clicks 统计表(按小时聚合)
create table click_stats (
short_code varchar(10),
hour_bucket timestamp,
country varchar(2),
clicks bigint default 0,
primary key (short_code, hour_bucket, country)
);
3. 架构图(文字版)
Client → CDN/Edge Cache → Load Balancer → API Gateway
↘
URL Service (Go/Python)
↙ ↘
Redis Cache Database (Spanner)
↘ ↗
Analytics Pipeline (Dataflow)
4. 核心设计决策
| 决策点 | 选择 | 理由 |
|---|---|---|
| 短码长度 | 7 字符 Base62 | $62^7 \approx 3.5 \times 10^{12}$,足够 |
| ID 生成 | 分布式发号器(Zookeeper 段模式) | 趋势递增,对 B+ 树友好 |
| 存储 | Spanner(全球分布式) | Google 内部使用,强一致 |
| 缓存 | Redis Cluster | 读多写少,P95 延迟 < 5ms |
| 统计 | BigQuery + Dataflow | 流式分析,延迟可接受 |
追问:
- 如何防止短码碰撞?(先查重再写入,或者预生成一批无碰撞短码)
- 如果服务挂掉 5 分钟,用户点击短链会怎样?(浏览器缓存 302、CDN 缓存兜底、降级到静态页面)
- 如何支持短码过期删除?(TTL + 定时任务,过期后回收短码)
Google 的系统设计面试特别看重 trade-off 分析:每个设计决策都要能说出"为什么选 A 不选 B"。
Onsite Round 4:Googleness
核心问题
Googleness 是 Google 特有的行为面试维度,考察:
- Intellectual Humility(谦逊好学)
- Comfort with Ambiguity(拥抱模糊)
- Collaboration(协作能力)
- Putting Users First(用户至上)
问题 1:Tell me about a time you had to disagree with your team.
我回答了一个实习中的真实案例:团队想用 A 方案(简单但可扩展性差),我坚持用 B 方案(前期开发成本高但长期维护成本低)。最后通过数据对比(预估 6 个月后的维护成本)说服了团队。
面试官追问:如果最终数据证明你错了呢?
- 答:承认错误,分析原因,总结经验,并且在团队内部分享这个决策过程中的教训。
问题 2:Describe a project where requirements were unclear.
我讲了学校的一个研究项目,导师只给了研究方向,没有明确的问题定义。我如何通过与导师每周 sync、快速原型验证、文献调研来逐步明确问题。
问题 3:How do you handle feedback?
我提到了实习期间 code review 中被指出设计模式使用不当,我主动学习了相关模式并在后续 PR 中应用。
HC 与 Team Match
Hiring Committee
HC 由 3-4 名资深工程师组成,交叉审核所有面试反馈:
- Hiring Signal:Strong Hire / Hire / Lean Hire / No Hire
- Level Calibration:确认你是 L3 还是 L4
- Red Flags:任何一轮面试中的疑虑都会被挑战
我的反馈整体是 Hire,算法两轮都是 Strong Hire,系统设计是 Hire,Googleness 是 Hire。
Team Match
Google 的 Team Match 是双向匹配:
- Recruiter 把你的简历和面试评分发给多个 hiring manager
- Hiring manager 有兴趣会安排 15-30min 的 casual chat
- 你对 team 也有选择权(可以 say no)
我聊了两个 team:
- Chrome Performance:浏览器性能优化,C++ 为主
- Search Infrastructure:搜索后端基础设施,Java/C++ 混合
最终选择了 Search Infra,因为跟我的实习经历更相关。
签证与入职
Google 对国际学生很友好:
| 阶段 | 说明 |
|---|---|
| H-1B | 每年 4 月抽签,抽中后 10.1 生效 |
| STEM OPT | 先用 EAD 入职,抽中后 transfer |
| 不抽中 | Google 会安排加拿大温哥华 office 入职,L1 签证一年后 transfer |
我的时间线是:11.1 offer → 11.15 提交 H-1B 材料 → 次年 3 月抽中 → 10.1 H-1B 生效。
面试复盘与建议
| 维度 | 表现 | 建议 |
|---|---|---|
| 算法 | ⭐⭐⭐⭐⭐ Strong Hire | 重点准备 Follow-up 和优化,原题难度不够 |
| 系统设计 | ⭐⭐⭐⭐ Hire | 多画架构图,每个决策讲 trade-off |
| Googleness | ⭐⭐⭐⭐ Hire | 准备 5-8 个 STAR 故事,重点突出团队协作 |
Google 面试的真相:
- 算法要顶尖:不是会做题就行,要能在 30 分钟内写出 bug-free 代码并分析时空复杂度。
- 沟通很重要:边写边说,让面试官知道你在想什么。
- Follow-up 是精髓:原始题目只是开胃菜,后续的扩展和优化才是区分度所在。
推荐阅读:
- 《Cracking the Coding Interview》(算法基础)
- 《Designing Data-Intensive Applications》(系统设计圣经)
- Google 官方招聘博客:careers.google.com/how-we-hire
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。