← 返回博客列表
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
    
    for i in range(start, n):
        if arr[i] != i + 1:
            return False, -1
    
    return True, start

第三步:如果是循環位移,計算需要的循環移位次數

return start  # 需要 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
    
    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
    
    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)
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])

第二步:使用雙向鏈表維護前驅後繼

第三步:處理重定向,刪除已訪問的節點

完整代碼

from collections import defaultdict

def getServerCoordinates(locations, redirectRecords):
    """
    Q2: 服務器重定向
    
    從 locations[0] 開始,按照 redirectRecords 重定向
    返回最終到達的服務器坐標
    """
    if not locations:
        return []
    
    n = len(locations)
    visited = set()
    
    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:
            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:
            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:
            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:
            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