← 返回博客列表
Google

🚨 Google 2026 面試真題:小島撤離航班調度 —— 看似簡單的貪心,為何90%的人都栽了?

2026-01-19

製造焦慮:打破幻覺

最近 Google 的面試真題在各大求職群瘋傳。

很多人第一眼看到題目的反應是:「這不就是排序 + 模擬嗎?秒了!」

大錯特錯。

如果你只是寫個暴力模擬,恭喜你,面試官會微笑著追問你三個 Followup,然後你就 Rej 了。

我們 oavoservice 團隊第一時間拿到了這道真題,深挖後發現裡面藏著大量關於 Greedy AlgorithmBinary SearchEdge Case 的考察點。


題目拆解:展示專業

🔍 原題描述

You're on a remote island that needs evacuation due to pending flooding. The government is sending planes tomorrow to get some people out. If you miss the last plane you'd have to take a slower boat the following day which you don't want. Given the plane schedule and the schedule of all your fellow islanders, What is the latest you could get to the airport tomorrow and still get evacuated?

📝 中文翻譯

你被困在一個即將被洪水淹沒的偏遠小島上。

政府明天會派出多班飛機來撤離部分島民。

如果你錯過所有航班,只能第二天坐慢船離開(你肯定不想這樣)。

已知:

規則:先到先上,座位有限

問題:你最晚什麼時候到達機場,還能保證坐上飛機?


深度複盤:建立信任

🧠 題目本質分析

這道題表面是「調度問題」,實際考察的是:

考點 具體內容
貪心思維 如何分配乘客到航班?
二分查找 如何高效找到臨界時間點?
邊界處理 航班滿員、無航班、時間衝突等 Edge Case
複雜度優化 從 O(n²) 暴力到 O(n log n) 優化

📊 輸入輸出格式

輸入:
- flights: List[(departure_time, capacity)]  # 航班列表:(起飛時間, 座位數)
- arrivals: List[int]  # 其他島民到達機場的時間

輸出:
- int: 你能保證上機的最晚到達時間
- 如果無論如何都上不了飛機,返回 -1

🎯 範例分析

Example 1:

flights = [(100, 2), (200, 1)]  # 航班1: 100時刻起飛,2座位;航班2: 200時刻起飛,1座位
arrivals = [50, 80]  # 兩個島民分別在50和80時刻到達

輸出: 199

解釋:
- 航班1(100起飛,2座位):在100之前到達的人可以上
  - 島民A(50)、島民B(80) 都能上,佔滿2個座位
- 航班2(200起飛,1座位):在200之前到達的人可以上
  - 沒有其他人搶這班,你只要在199之前到就行

所以答案是 199

Example 2:

flights = [(100, 1)]  # 只有一班航班,1個座位
arrivals = [50]  # 一個島民在50時刻到達

輸出: 49

解釋:
- 唯一的航班在100起飛,只有1個座位
- 島民A在50到達,如果你在50之後到,座位就被搶了
- 所以你必須在49或更早到達

Example 3:

flights = [(100, 1)]
arrivals = [50, 60]  # 兩個島民

輸出: -1

解釋:
- 只有1個座位,但有2個島民比你先到(假設你不能比所有人都早)
- 無論你什麼時候到,都沒有座位了
- 返回 -1

方案引入:核心演算法

思路一:暴力模擬 O(n × m × log m)

最直觀的想法:枚舉你的到達時間,模擬整個登機過程。

def latest_arrival_brute_force(flights, arrivals):
    """
    暴力解法:枚舉所有可能的到達時間
    flights: List[(departure_time, capacity)]
    arrivals: List[int] - 其他島民的到達時間
    """
    # 收集所有可能的時間點
    all_times = set(arrivals)
    for dep, _ in flights:
        all_times.add(dep - 1)  # 航班起飛前一刻
        all_times.add(dep)
    
    all_times = sorted(all_times, reverse=True)  # 從晚到早枚舉
    
    for my_time in all_times:
        if can_board(flights, arrivals, my_time):
            return my_time
    
    return -1

但這樣太慢了!讓我們優化...

思路二:正確的貪心策略

核心洞察

  1. 航班按起飛時間排序
  2. 乘客按到達時間排序
  3. 每個乘客貪心地選擇「能上的最早航班」
  4. 二分查找你的最晚到達時間

思路三:最終正確版本

def latest_arrival_time(flights, arrivals):
    """
    Google 面試真題:小島撤離
    
    Args:
        flights: List[Tuple[int, int]] - (起飛時間, 座位數)
        arrivals: List[int] - 其他島民的到達時間
    
    Returns:
        int: 你能保證上機的最晚到達時間,-1 表示無法撤離
    """
    if not flights:
        return -1
    
    # 按起飛時間排序
    flights = sorted(flights, key=lambda x: x[0])
    n_flights = len(flights)
    
    # 總座位數
    total_seats = sum(cap for _, cap in flights)
    
    # 如果座位不夠所有人(包括你)
    if total_seats <= len(arrivals):
        return -1
    
    def simulate(my_time):
        """
        模擬在 my_time 到達時能否登機
        返回 True 表示能成功撤離
        """
        # 所有人按到達時間排序
        everyone = sorted(arrivals + [my_time])
        
        # 每個航班的剩餘座位
        seats = [cap for _, cap in flights]
        
        # 指向當前考慮的航班
        flight_ptr = 0
        
        for person_arrival in everyone:
            # 找到第一個「起飛時間 > 到達時間」的航班
            while flight_ptr < n_flights and flights[flight_ptr][0] <= person_arrival:
                flight_ptr += 1
            
            # 從 flight_ptr 開始找有座位的航班
            boarded = False
            for i in range(flight_ptr, n_flights):
                if seats[i] > 0:
                    seats[i] -= 1
                    boarded = True
                    break
            
            if not boarded and person_arrival == my_time:
                return False
        
        return True
    
    # 二分查找最晚到達時間
    # 最早可能是 0,最晚是最後一班起飛前一刻
    lo, hi = 0, flights[-1][0] - 1
    result = -1
    
    while lo <= hi:
        mid = (lo + hi) // 2
        if simulate(mid):
            result = mid
            lo = mid + 1
        else:
            hi = mid - 1
    
    return result

🧪 測試用例

# Test 1: 基本情況
flights1 = [(100, 2), (200, 1)]
arrivals1 = [50, 80]
print(latest_arrival_time(flights1, arrivals1))  # 預期: 199

# Test 2: 緊張情況
flights2 = [(100, 1)]
arrivals2 = [50]
print(latest_arrival_time(flights2, arrivals2))  # 預期: 49

# Test 3: 無法撤離
flights3 = [(100, 1)]
arrivals3 = [50, 60]
print(latest_arrival_time(flights3, arrivals3))  # 預期: -1

# Test 4: 多航班複雜情況
flights4 = [(50, 1), (100, 2), (150, 1)]
arrivals4 = [30, 40, 60, 90]
print(latest_arrival_time(flights4, arrivals4))  # 需要仔細分析

# Test 5: 邊界 - 沒有其他人
flights5 = [(100, 1)]
arrivals5 = []
print(latest_arrival_time(flights5, arrivals5))  # 預期: 99

# Test 6: 邊界 - 沒有航班
flights6 = []
arrivals6 = [50]
print(latest_arrival_time(flights6, arrivals6))  # 預期: -1

複雜度分析

方法 時間複雜度 空間複雜度
暴力枚舉 O(T × n × m) O(n + m)
二分 + 模擬 O(log T × (n + m) log(n + m)) O(n + m)

其中:


🤯 面試官的 Followup 陷阱

Followup 1: 如果航班數量很大怎麼辦?

考點:優化模擬過程

當前解法每次模擬是 O((n + m) log(n + m)),如果 n 很大,可以用 線段樹樹狀數組 優化座位分配。

Followup 2: 如果要求返回你應該坐哪班航班?

def latest_arrival_with_flight(flights, arrivals):
    """返回 (最晚到達時間, 應該坐的航班索引)"""
    # ... 在 simulate 函數中記錄你上的是哪班航班
    pass

Followup 3: 如果有多個「你」,都想盡量晚到?

考點:博弈論 / 多人優化

這就變成了一個更複雜的調度問題,需要考慮納什均衡。

Followup 4: 如果航班可能延誤呢?

考點:魯棒性設計

需要考慮概率模型和風險評估。


🔥 為什麼大多數人會掛?

常見錯誤 正確做法
只考慮「我能不能上」 需要模擬所有人的登機過程
暴力枚舉所有時間點 二分查找優化
忽略「先到先上」規則 貪心策略:早到的人上早航班
Edge Case 處理不當 無航班、滿員、時間邊界

📞 oavoservice 服務

這種場景建模 + 貪心 + 二分的組合題,是 Google 面試的經典風格。

如果你在面試中遇到類似題目,我們可以提供:


👉 立即添加微信:Coding0201

不要讓一道調度題,毀掉你的 Google Offer。


本文由 oavoservice 團隊原創,轉載請註明出處。