這類 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(一維座標),你必須嚴格按題目流程重複:
- 你從「目前貨物位置」帶著貨 走到 最近的 station
- 用該 station 的無人機把貨送出去(每次 最多 10 單位,朝
target方向) - 若無人機沒送到
target:你要 空手 走到貨物落點把貨取回(此段不計入答案) - 重複直到送達
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
題目概述
給定兩個陣列 primary 與 secondary,以及一系列操作:
[0, index, val]:更新secondary[index] = val[1, targetSum]:查詢滿足primary[i] + secondary[j] == targetSum的 pair 數量
其中:
primary固定不變secondary會頻繁更新
正解:頻率表 + 動態維護
這是典型「固定 + 動態」Two-Sum 變體:
- 對
primary建freqA(固定) - 對
secondary建freqB(會變)
更新:
- 舊值在
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,獲得真題。