VO辅助 / 面试训练复盘

Amazon SDE NG 四轮面经|3轮 Code + 1轮 BQ,GenAI 成固定考察项

Amazon SDE 26 NG 的四轮 VO,每轮约一小时,结构都是 BQ + Coding。BQ 全程围绕 Leadership Principles,Bar Raiser 轮追问最狠;Coding 从 Medium 到 Hard 都有,GenAI 问答穿插在中间轮次。本文完整还原四轮题目与过程。

Amazon SDE NG 四轮 VO:并查集网格、滑动窗口、OOD 计价与纯 BQ
训练主题配图 · 非客户现场证明

Amazon SDE 26 NG 的四轮 VO 面完了,整体感受是经典题还是那些经典题,但强度比往年上了一个台阶:BQ 追问更细、GenAI 成了固定考察项。四轮每轮约一小时,结构都是 BQ + Coding。BQ 全程围绕 LP(Leadership Principles)展开,Bar Raiser 轮追问最狠;Coding 难度从 Medium 到 Hard 都有,新增的 GenAI 问答穿插在中间轮次。

第一轮:BQ + Coding

开场先聊了两个 BQ:和资深工程师在技术方案上意见不一致时怎么处理;讲一次项目临近 deadline 但执行过程中出现意外问题的经历。回答要落到「你发现了什么、提出了什么、如何推动、结果如何」,而不是停在「我们做了什么」。

Coding 是一道二维网格题。网格中有若干座塔,塔之间可以沿同行或同列传播信号,障碍物 M 会阻断传播,但中间的塔可以继续中继,要求找出所有能够互相通信的塔组。

这题可以用并查集。先把每座塔初始化成独立集合,然后逐行扫描:遇到障碍物就清空当前方向的前驱;遇到塔时,就和该行上一个未被障碍物隔开的塔合并。之后再逐列执行同样的操作。扫描结束后,根据每座塔的根节点完成分组。

class DSU:
    def __init__(self, n):
        self.p = list(range(n))
    def find(self, x):
        while self.p[x] != x:
            self.p[x] = self.p[self.p[x]]
            x = self.p[x]
        return x
    def union(self, a, b):
        ra, rb = self.find(a), self.find(b)
        if ra != rb:
            self.p[ra] = rb

def tower_groups(grid):
    R, C = len(grid), len(grid[0])
    idx = {}
    dsu = DSU(R * C)
    for r in range(R):
        for c in range(C):
            if grid[r][c] == 'T':
                idx[(r, c)] = r * C + c
    for r in range(R):
        prev = None
        for c in range(C):
            if grid[r][c] == 'M':
                prev = None
            elif grid[r][c] == 'T':
                if prev is not None:
                    dsu.union(prev, idx[(r, c)])
                prev = idx[(r, c)]
    for c in range(C):
        prev = None
        for r in range(R):
            if grid[r][c] == 'M':
                prev = None
            elif grid[r][c] == 'T':
                if prev is not None:
                    dsu.union(prev, idx[(r, c)])
                prev = idx[(r, c)]
    groups = {}
    for (r, c), i in idx.items():
        groups.setdefault(dsu.find(i), []).append((r, c))
    return list(groups.values())

Follow-up 问到了复杂度,以及如果网格很大、无法全部放进内存应该怎么处理。并查集本体是近似 O(α(n)),扫描是 O(R×C);内存放不下时可以按行或按列分块处理,只保留「当前行/列的前驱塔」这一层状态,边读边合并,再把并查集状态落盘分治。

第二轮:Coding

这一轮连续做了三道题,整体偏字符串和数组。

第一题:无重复字符的最长子串

使用滑动窗口和哈希表记录字符最近一次出现的位置。发现重复字符时,直接把左边界移动到该字符上次出现位置的下一位,并在过程中更新最大窗口长度。

def longest_unique_substring(s):
    last = {}
    left = ans = 0
    for right, ch in enumerate(s):
        if ch in last and last[ch] >= left:
            left = last[ch] + 1
        last[ch] = right
        ans = max(ans, right - left + 1)
    return ans

第二题:出现次数最多的非禁用词

给出一段文本和禁用词列表,返回出现次数最多且不在禁用列表中的单词;次数相同时返回更早达到该频率的单词。实现时不用正则,逐字符扫描,把标点转为空格、保留字母和数字、统一转成小写,禁用词放 Set,词频用哈希表统计。

def most_common_word(text, banned):
    banned = set(banned)
    freq = {}
    order = {}
    t = 0
    word = []
    for ch in text.lower():
        if ch.isalnum():
            word.append(ch)
        else:
            if word:
                w = ''.join(word)
                word = []
                if w in banned:
                    continue
                freq[w] = freq.get(w, 0) + 1
                order.setdefault(w, t)
                t += 1
    # 次数高者优先,次数相同取更早到达者
    return max(freq, key=lambda w: (freq[w], -order[w]))

第三题:旋转升序数组中查找目标值

在可能包含重复元素的旋转升序数组中查找目标值。主体还是二分查找:每轮先判断哪一半有序,再根据目标值范围缩小搜索区间。如果 left、mid、right 三个位置的值相同,无法判断有序区间,就同时收缩左右边界,避免陷入死循环。

def search_rotated(nums, target):
    l, r = 0, len(nums) - 1
    while l <= r:
        m = (l + r) // 2
        if nums[m] == target:
            return True
        if nums[l] == nums[m] == nums[r]:
            l += 1
            r -= 1
        elif nums[l] <= nums[m]:
            if nums[l] <= target < nums[m]:
                r = m - 1
            else:
                l = m + 1
        else:
            if nums[m] < target <= nums[r]:
                l = m + 1
            else:
                r = m - 1
    return False

第三轮:OOD

BQ 先问了一次「不得不跳出舒适圈、快速学习陌生技术」的经历。

OOD 是设计一个快递运费计价系统。运费由配送时效、箱子规格和增值服务共同决定,并且需要方便后续增加新的配送方式和计价规则。把配送方式、包装规格和增值服务分别抽象成独立对象,通过统一的计价接口计算费用;订单对象只负责保存用户选择,计价器负责组合各项价格规则。这样新增配送方式或服务时,只需增加新的实现,不用修改原有计算流程。

class ShippingMethod:
    def cost(self, order):
        raise NotImplementedError

class Express(ShippingMethod):
    def cost(self, order):
        return 20

class Standard(ShippingMethod):
    def cost(self, order):
        return 8

class AddOn:
    def cost(self, order):
        raise NotImplementedError

class PricingEngine:
    def __init__(self):
        self.methods = {}
        self.addons = []
    def calculate(self, order):
        base = self.methods[order.method].cost(order)
        extra = sum(a.cost(order) for a in self.addons)
        return base + extra

Follow-up 把问题扩展到了类似 Linux find 的文件搜索系统,需要支持按路径、大小和后缀过滤,并组合 AND、OR、NOT 条件。这里继续使用策略模式和组合模式:每个筛选条件实现统一的 Filter 接口,复合条件负责组合多个 Filter,搜索器只负责遍历文件并执行规则。

第四轮:BQ

最后一轮全程是行为问题,追问集中在个人贡献和决策过程。典型问题包括:主动解决了一个棘手问题但团队里没有明确负责人;信息不完整时做过的重要决定及风险评估;与资深工程师意见相左时如何沟通;真实的代码重构案例及其可维护性改善;如何与产品、测试和其他工程团队合作。

这轮最好提前准备真实案例。回答时不要只讲「我们做了什么」,要明确自己发现了什么问题、提出了什么方案、如何推动落地,以及最后取得了什么结果。GenAI 的考察通常落在「如何用大模型辅助定位问题、生成代码、写测试」,重点是讲清你如何验证生成结果、控制上下文与幻觉,把 AI 当协作工具同时保留人工校验环节。

FAQ

Amazon 的 GenAI 考察到底在考什么?

考的是把大模型当作生产力工具时的工程判断:如何写 prompt、如何验证生成代码、控制上下文与幻觉、何时人工介入。能讲清「生成 + 校验」闭环,比会背模型名更有说服力。

网格很大的塔通信题怎么处理内存?

并查集状态可以按行/列分块落盘,边扫描边合并,只保留当前方向的前驱塔;也可以先做一轮外部排序把同行/同列的塔聚在一起再分组。

参考来源

联系 VOPathway

如果你希望把这套方法用于自己的 OA 或 VO 准备,可以把目标岗位、当前阶段、面试时间和主要难点发给 VOPathway,我们会据此安排针对性的练习与复盘。

  • 微信:Coding0201
  • 邮箱:[email protected]
  • Telegram:@OAVOProxy
  • WhatsApp:+86 178 6396 8105

可提供 OA辅助、OA辅导、VO辅助与 VO辅导。文章用于训练参考,不代表相关公司的官方流程;实际安排请以候选人收到的通知为准。

每一步,都更接近准备充分的自己。

本文用于面试准备与训练复盘。公司名称仅用于标识题型素材主题,不代表官方合作或录用承诺。

预约一次训练复盘 ↗