目录
正在加载目录...

Snowflake面经 | Snowflake OA + 面经分享

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 种

解题思路

  1. dp[i] 表示从位置 i 开始的子字符串能够划分为质数的有效方法总数,最终返回 dp[0]
  2. 从字符串的末尾开始向前遍历,如果当前位置是 ‘0’,则跳过,因为数字不能以 0 开头。
  3. 对于从 i 开始的每个子串,尝试将其转化为数字,并检查该数字是否是质数。如果是质数,则将 dp[i] 更新为当前值加上从该数字之后的分割方式数(即 dp[j+1])。
  4. 最终的答案是 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,统计有多少个连续子串满足:

  1. 子串只包含元音字符(a/e/i/o/u),不能出现辅音;
  2. 子串中 a、e、i、o、u 五个元音都至少出现一次。

返回满足条件的子串数量(输入规模最大 1e5)。

例子

输入:s = "aaeiouxa"
输出:2
解释:符合的子串有两个:
s[0:5] = "aaeiou"
s[1:5] = "aeiou"

解题思路

  1. 如果字符是元音:
    • 更新 last_seen 中该元音字母的最新出现位置为 i
    • 检查 last_seen 中的所有元音字母的位置是否都在 last_consonant 之后(即全部元音都已出现在当前区间内)。
    • 如果所有元音字母都出现在 last_consonant 之后,则计算子串数量:
      • 增加的数量是 min(last_seen.values()) - last_consonant,即 当前区间 中第一次包含所有元音字母的位置减去最后一个辅音的位置。
  2. 如果字符是辅音:
    • 更新 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 count

Question 3:Maximum Order Volume

题目:题目的意思是给定若干带权区间(电话的开始时间和结束时间),在区间不重叠的前提下,选择一组区间使其权重之和最大。

解题思路

  1. 收集时间点:提取所有电话的开始时间结束时间,并存储在集合中,避免重复。
  2. 时间索引映射:将每个时间点映射为一个索引,方便在动态规划数组中操作。
  3. 呼叫与时间索引的关联:将每个电话呼叫按开始时间的索引存储起来,以便在动态规划中使用。
  4. 动态规划计算最大音量
    • 遍历每个时间点索引,计算从起点到当前时间的最大音量
    • 如果该时间点有电话呼叫,则更新该呼叫的结束时间的最大音量
  5. 返回结果:最终返回从时间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 水平线的位置。

澄清问题提问

  1. 是否可以从蛋糕中间去切分? 可以
  2. 水平线的位置可以不是整数吗? 可以
  3. 有可能有多个答案,是否返回一个就可以了? 输出一个可行解就可以了
  4. 每个蛋糕所给的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面经 | 面试内容
  1. Snowflake 的Code是出了名的难和复杂,可以刷刷近30天的Tag题,VO整体时间自己把握,代码要写完;
  2. Snowflake主要是Code要好好准备,NG还会有System design;
  3. 从OA到VO完全是纯玄学,OA全过也有可能收不到VO,可以托朋友去问流程,但不知道有没有帮助。

Interview Aid 专注北美技术岗位的面试辅助,如果你近期也拿到Snowflake的面试,可以与我们联系,我们免费提供Snowflake OA真题和 Snowflake面经 参考。

正文完