Snowflake作为 Modern Data Stack 的核心,其 Software Engineer 已成为数据领域最具挑战性也最具吸引力的岗之一。与传统SDE的面试不同,Snowflake SDE 的面试,尤其看重你的“云原生思维”、“成本优化意识”和“平台特性深度应用”,分享下最近遇到的 Snowflake面经 和 OA。
Snowflake面试时间线
Timeline(2025.11 – 2026.1)
- 11.21 内推
- 11.22 收到并完成 OA
- 12.3 HR call
- 12.10 完成 work authorization form
假期出去玩了所以 VO 约得比较晚
- 12.12 VO1
- 12.15 VO2
- 12.19 通知面试通过,约 HM call
- 1.6 第一个 HM call,当天收到另外三个 HM call,连续三个 HM call,当天通知后面三个 HM 都过了
- 1.8 HR 打电话催选组
- 1.9 提交 reference check,约 offer call
- 1.19 offer call
整体来说 snow 效率还是很高的,面试体验也不错。
Snowflake OA 真题 & 解答
Question 1:Prime String
题目:给定一个数字字符串,统计在不改变顺序的前提下,将其切分为若干个 合法质数子串 的方案数,结果对 1e9+7 取模,这其实是一个字符串切分 + 质数判断 + 动态规划计数的题目。
例子
s = "11375",可以这样切:
11 | 37 | 5
11 | 3 | 7 | 5
113 | 7 | 5
共 3 种解题思路
dp[i]表示从位置i开始的子字符串能够划分为质数的有效方法总数,最终返回dp[0]。- 从字符串的末尾开始向前遍历,如果当前位置是 ‘0’,则跳过,因为数字不能以 0 开头。
- 对于从
i开始的每个子串,尝试将其转化为数字,并检查该数字是否是质数。如果是质数,则将dp[i]更新为当前值加上从该数字之后的分割方式数(即dp[j+1])。 - 最终的答案是
dp[0],即从位置 0 开始可以形成多少种有效的质数分割。
代码
def countPrimeStrings(s):
MOD = 10**9 + 7
n = len(s)
max_num = 10**6
is_prime = [False, False] + [True] * (max_num - 1)
primes = []
for i in range(2, max_num + 1):
if is_prime[i]:
primes.append(i)
for p in primes:
if i * p > max_num:
break
is_prime[i * p] = False
if i % p == 0:
break
dp = [0] * (n + 1)
dp[n] = 1
for i in range(n - 1, -1, -1):
if s[i] == '0':
continue
num = 0
for j in range(i, min(i + 6, n)):
num = num * 10 + int(s[j])
if num > max_num:
break
if is_prime[num]:
dp[i] = (dp[i] + dp[j + 1]) % MOD
return dp[0]
print(countPrimeStrings("11375"))Question 2:Vowel Substring
题目:给定一个小写字母字符串 s,统计有多少个连续子串满足:
- 子串只包含元音字符(a/e/i/o/u),不能出现辅音;
- 子串中 a、e、i、o、u 五个元音都至少出现一次。
返回满足条件的子串数量(输入规模最大 1e5)。
例子
输入:s = "aaeiouxa"
输出:2
解释:符合的子串有两个:
s[0:5] = "aaeiou"
s[1:5] = "aeiou"解题思路
- 如果字符是元音:
- 更新
last_seen中该元音字母的最新出现位置为i。 - 检查
last_seen中的所有元音字母的位置是否都在last_consonant之后(即全部元音都已出现在当前区间内)。 - 如果所有元音字母都出现在
last_consonant之后,则计算子串数量:- 增加的数量是
min(last_seen.values()) - last_consonant,即 当前区间 中第一次包含所有元音字母的位置减去最后一个辅音的位置。
- 增加的数量是
- 更新
- 如果字符是辅音:
- 更新
last_consonant为当前字符的位置i,表示从这个位置之后的子串才可能重新满足条件
- 更新
代码
def vowelsubstring(s):
vowels = set('aeiou')
count = 0
last_consonant = -1
last_seen = {v: -1 for v in vowels}
for i, char in enumerate(s):
if char in vowels:
last_seen[char] = i
if all(pos > last_consonant for pos in last_seen.values()):
count += min(last_seen.values()) - last_consonant
else:
last_consonant = i
return countQuestion 3:Maximum Order Volume
题目:题目的意思是给定若干带权区间(电话的开始时间和结束时间),在区间不重叠的前提下,选择一组区间使其权重之和最大。
解题思路
- 收集时间点:提取所有电话的开始时间和结束时间,并存储在集合中,避免重复。
- 时间索引映射:将每个时间点映射为一个索引,方便在动态规划数组中操作。
- 呼叫与时间索引的关联:将每个电话呼叫按开始时间的索引存储起来,以便在动态规划中使用。
- 动态规划计算最大音量:
- 遍历每个时间点索引,计算从起点到当前时间的最大音量。
- 如果该时间点有电话呼叫,则更新该呼叫的结束时间的最大音量。
- 返回结果:最终返回从时间0到最后时间点的最大音量和。
代码
def phoneCalls(start, duration, volume):
n = len(start)
st = set()
st.add(0)
for i in range(n):
st.add(start[i])
st.add(start[i] + duration[i] - 1)
hp = {}
ptr = 0
for k in sorted(st):
hp[k] = ptr
ptr += 1
g = {}
for i in range(n):
k = hp[start[i]]
if k not in g:
g[k] = []
g[k].append(i)
dp = [0] * ptr
for i in range(1, ptr):
dp[i] = max(dp[i], dp[i - 1])
if i in g:
for id in g[i]:
d = start[id] + duration[id] - 1
dk = hp[d]
dp[dk] = max(dp[dk], dp[i - 1] + volume[id])
return dp[ptr - 1]Snowflake 面经
Snowflake VO 1
题目:给一个table,table是无限大的,给很多的蛋糕,每个蛋糕都是一个正方形,蛋糕的变长是可以变化 让找出一个水平线,可以把table分成2半,table上边的蛋糕面积和table下边的是一样大 input: list[cake] , cake{x,y,side} output: float 水平线的位置。
澄清问题提问
- 是否可以从蛋糕中间去切分? 可以
- 水平线的位置可以不是整数吗? 可以
- 有可能有多个答案,是否返回一个就可以了? 输出一个可行解就可以了
- 每个蛋糕所给的x和y,是蛋糕的哪个位置? 是蛋糕的左上角
解题思路
分析:假定一个水平线 如果这个水平线更靠下,就更有可能水平线上方的蛋糕面积过大,超过总面积的一半 如果这个水平线更靠上,就更有可能水平线上方的蛋糕面积过小,小于总面积的一半 说明就可以反复的进行二分,找到刚好,上下两遍面积一样大的水平线的位置。
算法实现
1. 使用二分搜索目标: 找一个水平线的位置,满足: 水平线的上边的蛋糕面积 = 下边的蛋糕面积;
2. 二分的搜索范围 水平线的范围就在最上边蛋糕的上边界,还有最下面蛋糕的下边界 left = 最上边蛋糕的上边界,right = 最下面蛋糕的下边界;
3. 调整边界 先取中间值mid所为水平线的位置 通过遍历所有的蛋糕,如果蛋糕有一部分/全部在这个水平线的上面,就进行累加。
Snowflake VO 2
题目要求实现一个 Average 类,包含两个核心方法:
1. add(num) 方法
- 用于向集合中添加一个数字;
- 集合初始化的窗口大小 N;
- 当集合大小达到 N 时:
- 需要移除最早加入的元素,再插入新元素;
- 集合中元素必须保持添加顺序。
2. getAverage(K) 方法
- 若 K < 当前集合大小:
- 需要从集合中移除 K 个元素;
- 根据示例,实际规则是:移除 K 个最小元素;
- 使用剩余元素计算平均值;
- 若 K ≥ 当前集合大小:直接使用全部元素计算平均值;
- 平均值结果需要保留两位小数;
解题思路
首先,使用一个有序列表维护元素的添加顺序,以满足:
add方法窗口有大小限制并且有先进先出的逻辑;getAverage方法中“移除元素后仍需保持原始顺序”的约束。
在计算平均值时通过列表副本排序的方式,确定需要移除的 K 个最小元素,再通过遍历原列表进行筛选,在不破坏顺序的前提下完成移除即可。
了解更多

- Snowflake 的Code是出了名的难和复杂,可以刷刷近30天的Tag题,VO整体时间自己把握,代码要写完;
- Snowflake主要是Code要好好准备,NG还会有System design;
- 从OA到VO完全是纯玄学,OA全过也有可能收不到VO,可以托朋友去问流程,但不知道有没有帮助。
Interview Aid 专注北美技术岗位的面试辅助,如果你近期也拿到Snowflake的面试,可以与我们联系,我们免费提供Snowflake OA真题和 Snowflake面经 参考。