← 返回博客列表
Amazon

Amazon OA 2026 Intern 真题复盘|排列排序 + 服务器重定向完整解析

2026-03-16

Amazon OA 2026 Intern 真题复盘|排列排序 + 服务器重定向完整解析

Amazon OA Question 1

导读:Amazon 2026 Intern OA 考试以实际工程问题著称。这两道题考察的是系统优化中的核心问题:如何高效排序排列,以及如何在分布式系统中智能路由请求。第一题考察贪心策略和循环检测,第二题考察高级数据结构和路径压缩优化。


📌 题目一:排列排序(Permutation Sorter)

问题描述

给定一个 1 到 n 的排列,有两种操作:

  1. 反转操作:将整个数组反转
  2. 循环移位操作:将第一个元素移到最后

求用最少操作次数将排列变成升序 [1, 2, 3, ..., n]。

示例

n = 10
arr = [2, 3, 4, 5, 6, 7, 8, 9, 10, 1]

操作1:反转 → [1, 10, 9, 8, 7, 6, 5, 4, 3, 2]
操作2:循环移位 → [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
操作3:反转 → [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

最少操作数 = 3

核心思路

关键观察:排列只能通过反转和循环移位两种操作变换。

方法一:检查特殊情况

第一步:检查当前数组是否已是升序

if arr == sorted(arr):
    return 0

第二步:检查是否为循环位移的升序

def is_cyclic_sorted(arr):
    n = len(arr)
    # 找到第一个"断点"
    start = 0
    while start < n and arr[start] == start + 1:
        start += 1
    
    if start == n:
        return True, 0  # 已排序
    
    # 检查从start开始是否为循环升序
    for i in range(start, n):
        if arr[i] != i + 1:
            return False, -1
    
    return True, start  # 返回循环位移的起始位置

第三步:如果是循环位移,计算需要的循环移位次数

# 需要 start 次循环移位将第一个元素移到正确位置
return start

方法二:检查反转后的循环位移

如果当前数组不是循环位移的升序,尝试反转后是否为循环位移的升序。

def find_min_operations(arr):
    n = len(arr)
    
    # 检查当前数组是否为循环位移的升序
    is_cyclic, shift_count = is_cyclic_sorted(arr)
    if is_cyclic:
        return shift_count
    
    # 反转数组后检查
    reversed_arr = arr[::-1]
    is_cyclic_rev, shift_count_rev = is_cyclic_sorted(reversed_arr)
    if is_cyclic_rev:
        return 1 + shift_count_rev  # 1次反转 + shift_count_rev次循环移位
    
    # 如果都不满足,需要更复杂的操作序列
    # 使用BFS找最短路径
    return bfs_min_operations(arr)

完整代码

from collections import deque

def findMinimumOperations(arr):
    """
    Q1: 排列排序
    
    给定排列,用反转和循环移位两种操作排序
    返回最少操作数
    """
    n = len(arr)
    target = list(range(1, n + 1))
    
    # 检查是否已排序
    if arr == target:
        return 0
    
    def is_cyclic_sorted(a):
        """检查是否为循环位移的升序"""
        start = 0
        while start < n and a[start] == start + 1:
            start += 1
        
        if start == n:
            return True, 0
        
        for i in range(start, n):
            if a[i] != i + 1:
                return False, -1
        
        return True, start
    
    # 检查当前数组
    is_cyclic, shift = is_cyclic_sorted(arr)
    if is_cyclic:
        return shift
    
    # 检查反转后的数组
    reversed_arr = arr[::-1]
    is_cyclic_rev, shift_rev = is_cyclic_sorted(reversed_arr)
    if is_cyclic_rev:
        return 1 + shift_rev
    
    # 使用BFS找最短路径
    queue = deque([(tuple(arr), 0)])
    visited = {tuple(arr)}
    target_tuple = tuple(target)
    
    while queue:
        current, ops = queue.popleft()
        
        # 反转
        reversed_tuple = tuple(reversed(current))
        if reversed_tuple == target_tuple:
            return ops + 1
        if reversed_tuple not in visited:
            visited.add(reversed_tuple)
            queue.append((reversed_tuple, ops + 1))
        
        # 循环移位
        rotated_tuple = current[1:] + (current[0],)
        if rotated_tuple == target_tuple:
            return ops + 1
        if rotated_tuple not in visited:
            visited.add(rotated_tuple)
            queue.append((rotated_tuple, ops + 1))
    
    return -1


# 测试用例
if __name__ == "__main__":
    print(findMinimumOperations([2, 3, 4, 5, 6, 7, 8, 9, 10, 1]))  # 输出: 3
    print(findMinimumOperations([1, 2, 3, 4, 5]))  # 输出: 0
    print(findMinimumOperations([5, 4, 3, 2, 1]))  # 输出: 1

复杂度分析

时间复杂度:O(n) 快速检查,O(n! × n) BFS 最坏情况
空间复杂度:O(n!)

面试要点

澄清问题:排列范围、是否保证有解、n 的范围
优化思路:先检查特殊情况再用 BFS
常见错误:没有检查循环位移、BFS 状态爆炸


📌 题目二:服务器重定向(Server Redirect)

Amazon OA Question 2

问题描述

在 2D 平面上有 n 个服务器,每个服务器由坐标 (x, y) 定义。给定 q 个重定向记录,每条记录指定一个方向。

请求从 locations[0] 开始,按照 4 个方向之一重定向到最近的未访问服务器:

其中 Z 是任意正整数。如果该方向没有服务器,则跳过。

求最终请求到达的服务器坐标。

核心思路

关键观察:

方法:分组 + 双向链表 + 路径压缩

第一步:按 (x-y) 和 (x+y) 分组

from collections import defaultdict

diff_map = defaultdict(list)  # diff_map[x-y] = [(x, y), ...]
sum_map = defaultdict(list)   # sum_map[x+y] = [(x, y), ...]

for i, (x, y) in enumerate(locations):
    diff_map[x - y].append(i)
    sum_map[x + y].append(i)

# 按 x 坐标排序
for key in diff_map:
    diff_map[key].sort(key=lambda i: locations[i][0])
for key in sum_map:
    sum_map[key].sort(key=lambda i: locations[i][0])

第二步:使用双向链表维护前驱后继,删除已访问的节点

class Node:
    def __init__(self, idx):
        self.idx = idx
        self.prev = None
        self.next = None

# 构建双向链表
diff_lists = {}
for key, indices in diff_map.items():
    nodes = [Node(idx) for idx in indices]
    for i in range(len(nodes) - 1):
        nodes[i].next = nodes[i + 1]
        nodes[i + 1].prev = nodes[i]
    diff_lists[key] = {indices[i]: nodes[i] for i in range(len(nodes))}

第三步:处理重定向,删除已访问的节点

def redirect(x, y, direction):
    if direction == 1:
        # x-y 不变,在 diff_map 中找最接近的
        key = x - y
        target_sum = x + y
        # 遍历链表找最接近的未删除节点
        ...
    # 类似处理其他方向

完整代码

from collections import defaultdict

def getServerCoordinates(locations, redirectRecords):
    """
    Q2: 服务器重定向
    
    从 locations[0] 开始,按照 redirectRecords 重定向
    返回最终到达的服务器坐标
    """
    if not locations:
        return []
    
    n = len(locations)
    visited = set()
    
    # 按 x-y 和 x+y 分组
    diff_map = defaultdict(list)
    sum_map = defaultdict(list)
    
    for i, (x, y) in enumerate(locations):
        diff_map[x - y].append(i)
        sum_map[x + y].append(i)
    
    # 排序
    for key in diff_map:
        diff_map[key].sort(key=lambda i: locations[i][0])
    for key in sum_map:
        sum_map[key].sort(key=lambda i: locations[i][0])
    
    # 当前位置
    current_idx = 0
    visited.add(current_idx)
    
    for direction in redirectRecords:
        x, y = locations[current_idx]
        next_idx = None
        
        if direction == 1:
            # (x, y) → (x+Z, y+Z),x-y 不变
            key = x - y
            target_sum = x + y
            
            best_dist = float('inf')
            for idx in diff_map[key]:
                if idx not in visited:
                    nx, ny = locations[idx]
                    dist = abs(nx + ny - target_sum)
                    if dist < best_dist:
                        best_dist = dist
                        next_idx = idx
        
        elif direction == 2:
            # (x, y) → (x+Z, y-Z),x+y 不变
            key = x + y
            target_diff = x - y
            
            best_dist = float('inf')
            for idx in sum_map[key]:
                if idx not in visited:
                    nx, ny = locations[idx]
                    dist = abs(nx - ny - target_diff)
                    if dist < best_dist:
                        best_dist = dist
                        next_idx = idx
        
        elif direction == 3:
            # (x, y) → (x-Z, y+Z),x+y 不变
            key = x + y
            target_diff = x - y
            
            best_dist = float('inf')
            for idx in sum_map[key]:
                if idx not in visited:
                    nx, ny = locations[idx]
                    dist = abs(nx - ny - target_diff)
                    if dist < best_dist:
                        best_dist = dist
                        next_idx = idx
        
        elif direction == 4:
            # (x, y) → (x-Z, y-Z),x-y 不变
            key = x - y
            target_sum = x + y
            
            best_dist = float('inf')
            for idx in diff_map[key]:
                if idx not in visited:
                    nx, ny = locations[idx]
                    dist = abs(nx + ny - target_sum)
                    if dist < best_dist:
                        best_dist = dist
                        next_idx = idx
        
        # 如果找到未访问的服务器,移动到该服务器
        if next_idx is not None:
            current_idx = next_idx
            visited.add(current_idx)
    
    return locations[current_idx]


# 测试用例
if __name__ == "__main__":
    locations = [[3, 4], [1, 2], [2, 7], [8, 5], [5, 6]]
    redirectRecords = [1, 4]
    print(getServerCoordinates(locations, redirectRecords))  # 输出: [5, 6]

复杂度分析

时间复杂度:O(n log n + q × n)
空间复杂度:O(n)

面试要点

澄清问题:方向定义、距离计算方式、是否保证有解
关键洞察:按 x-y 和 x+y 分组是关键、双向链表快速删除
常见错误:混淆方向、距离计算错误、没有处理已访问服务器


🎯 总结对比

题目 算法 时间复杂度 难度
Q1:排列排序 BFS + 贪心检查 O(n) / O(n! × n) ⭐⭐⭐
Q2:服务器重定向 分组 + 双向链表 O(n log n + q×n) ⭐⭐⭐

🚀 面试建议

  1. 时间管理:两道题共 90 分钟,建议各 45 分钟
  2. 代码质量:注重边界条件和数据结构选择
  3. 沟通能力:清晰解释分组策略和优化思路
  4. 优化意识:从暴力解到最优解的演进过程

📞 需要面试辅助?

oavoservice 提供专业的 OA/VO 辅助服务。

👉 立即添加微信:Coding0201