← 返回面經列表

Meta / CodeSignal OA 四題復盤:Q1 數位和貪心,Q2 無人機投遞模擬,Q3 電池充放電調度,Q4 動態 Two-Sum(含更新)

3 分鐘

這類 CodeSignal 風格 OA 的味道很一致:演算法不一定難,但規則很細、步驟很長。寫對的關鍵不是「腦補最優策略」,而是把題面限制逐條落成程式。

本文按 Q1 → Q4 復盤四題:

  • 題意重點
  • 最穩的實作策略
  • 常見翻車點
  • 可直接套用的程式模板

延伸閱讀:


Q1 — Minimum Sum After One Operation

題目概述

給定正整數陣列 nums,最多執行一次操作:

  • 選一個下標 i
  • nums[i] 替換成它的 各位數字之和

回傳執行 0 次或 1 次操作後,陣列總和的最小值。

核心思路(熱身題)

這題就是「算差值」的貪心:

  • 先算原始總和 S
  • 對每個數 x 計算 digitSum(x)
  • 替換後總和為 S - x + digitSum(x)
  • 取最小即可(也要考慮「不替換」)

複雜度

  • 時間:O(n * log10(max(nums)))
  • 空間:O(1)

Python 模板

def digit_sum(x: int) -> int:
    s = 0
    while x > 0:
        s += x % 10
        x //= 10
    return s


def min_sum_after_one_operation(nums: list[int]) -> int:
    S = sum(nums)
    ans = S
    for x in nums:
        ans = min(ans, S - x + digit_sum(x))
    return ans

Q2 — Delivery System Using Drones

題目概述

給定 target 距離與一組 stations(一維座標),你必須嚴格按題目流程重複:

  1. 你從「目前貨物位置」帶著貨 走到 最近的 station
  2. 用該 station 的無人機把貨送出去(每次 最多 10 單位,朝 target 方向)
  3. 若無人機沒送到 target:你要 空手 走到貨物落點把貨取回(此段不計入答案)
  4. 重複直到送達 target

回傳:你「帶著貨物步行」的總距離(空手走的不算)。

常見翻車點

  • stations 一定要先排序
  • 只有帶貨步行才計入,空手追貨不計入
  • 規則是「最近站點」,不是「往前的下一個站點」

穩妥模擬

只維護一個變數:cargoPos(貨物目前在哪)。

每輪:

  • 找到離 cargoPos 最近的站點 s
  • ans += abs(cargoPos - s),並令 cargoPos = s
  • 無人機把貨往 target 方向送 <= 10

Python 模板

import bisect


def nearest_station(pos: int, stations: list[int]) -> int:
    # stations 必須已排序
    j = bisect.bisect_left(stations, pos)

    cand = []
    if j < len(stations):
        cand.append(stations[j])
    if j - 1 >= 0:
        cand.append(stations[j - 1])

    # 若題面沒定 tie-break,建議距離相同時取較小座標,避免不穩定
    cand.sort(key=lambda s: (abs(s - pos), s))
    return cand[0]


def delivery_distance_with_cargo(target: int, stations: list[int]) -> int:
    stations.sort()

    cargo = 0
    ans = 0

    while cargo != target:
        s = nearest_station(cargo, stations)
        ans += abs(cargo - s)
        cargo = s

        if target >= cargo:
            cargo = min(target, cargo + 10)
        else:
            cargo = max(target, cargo - 10)

        # 若沒到 target:空手去拿貨(不計入),下一輪繼續

    return ans

Q3 — Battery Usage Simulation

題目概述

你希望手機持續運行總時長 t

有多顆電池:

  • capacity[i]:滿電可用時長
  • recharge[i]:從 0 充滿所需時間

規則:

  • 只能使用 fully-charged 的電池
  • 電池用完後立刻開始充電
  • 若需要用電池但沒有任何 fully-charged:回傳 -1
  • 很容易漏的邊界:最後一顆電池若使總時間 超過 t,通常視為不合法,回傳 -1(保守寫法是要求剛好湊到 t

核心模擬

nextFull[i] 表示第 i 顆電池下一次「充滿可用」的時間點。

  • 初始全滿:nextFull[i] = 0
  • 目前時間 cur
  • cur 時刻,所有滿足 nextFull[i] <= cur 的電池都可用
  • 用完後更新:nextFull[i] = cur + recharge[i]

實作上可用堆:

  • future:依「何時充滿」排序
  • ready:依「容量」排序(可用時取最大容量)

Python 模板(堆)

import heapq


def min_batteries_to_run(t: int, capacity: list[int], recharge: list[int]) -> int:
    n = len(capacity)

    # future: (time_when_full, idx)
    future = [(0, i) for i in range(n)]
    heapq.heapify(future)

    # ready: (-capacity, idx)
    ready = []

    cur = 0
    used = 0

    while cur < t:
        while future and future[0][0] <= cur:
            _, i = heapq.heappop(future)
            heapq.heappush(ready, (-capacity[i], i))

        if not ready:
            return -1

        cap_neg, i = heapq.heappop(ready)
        cap = -cap_neg

        cur += cap
        used += 1

        if cur > t:
            return -1

        heapq.heappush(future, (cur + recharge[i], i))

    return used

Q4 — Primary + Secondary Arrays with Operations

題目概述

給定兩個陣列 primarysecondary,以及一系列操作:

  • [0, index, val]:更新 secondary[index] = val
  • [1, targetSum]:查詢滿足 primary[i] + secondary[j] == targetSum 的 pair 數量

其中:

  • primary 固定不變
  • secondary 會頻繁更新

正解:頻率表 + 動態維護

這是典型「固定 + 動態」Two-Sum 變體:

  • primaryfreqA(固定)
  • secondaryfreqB(會變)

更新:

  • 舊值在 freqB 減 1(為 0 可刪)
  • 新值在 freqB 加 1

查詢:

  • 枚舉 freqA 裡的 distinct 值 a
  • 累加 freqA[a] * freqB[targetSum - a]

Python 模板

from collections import Counter


def process_operations(primary: list[int], secondary: list[int], operations: list[list[int]]) -> list[int]:
    freqA = Counter(primary)
    freqB = Counter(secondary)

    ans = []

    for op in operations:
        if op[0] == 0:
            idx, val = op[1], op[2]
            old = secondary[idx]

            freqB[old] -= 1
            if freqB[old] == 0:
                del freqB[old]

            secondary[idx] = val
            freqB[val] += 1

        else:
            target = op[1]
            total = 0
            for a, cntA in freqA.items():
                total += cntA * freqB.get(target - a, 0)
            ans.append(total)

    return ans

總結:這套四題考的是「工程化執行力」

  • Q1:算差值,別上強度
  • Q2:按流程模擬,別腦補路線
  • Q3:資源狀態機(可用/充電中),最後的邊界最陰
  • Q4:固定 + 動態 Two-Sum 結構,頻率表是王道

如果你在準備 Meta / CodeSignal 類 OA,建議把「模擬題」當成工程題來寫:

  • 先列流程
  • 再定狀態變數
  • 最後補 tie-break 與邊界條件

需要面試真題? 立刻聯繫微信 Coding0201,獲得真題


联系方式

Email: [email protected] Telegram: @OAVOProxy