这类 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(一维坐标),你要用“人 + 无人机站点”把货送到 target。
无人机规则:
- 每次从某个 station 放飞无人机,最多飞 10 单位(包括最终那一跳)
并且你必须严格按题目流程重复:
- 你从“当前货物位置”带着货走到 最近的 station
- 用该 station 的无人机把货送出去(最多 10 单位)
- 若无人机没飞到
target:你要 空手 走到货物落点取回货 - 重复直到送达
target
返回:你“带着货物步行”的总距离(空手走的不计入)。
易错点(Meta 很爱卡这里)
stations必须先排序,否则最近站点查找很容易写崩- 只有带货步行才计入答案,空手追货不计入
- 规则是“最近站点”,不是“下一个站点 / 往前走的站点”
稳妥模拟策略
只维护一个变量:cargoPos(货物当前在哪)。
每轮:
- 找到离
cargoPos最近的站点s ans += abs(cargoPos - s),然后cargoPos = s- 无人机把货往
target方向送<= 10:- 若
target >= cargoPos:cargoPos = min(target, cargoPos + 10) - 否则:
cargoPos = max(target, cargoPos - 10)
- 若
- 如果没到
target,你空手去取货,这段不计入;下一轮以新的cargoPos继续
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(不能> t)
核心模拟
用 nextFull[i] 表示第 i 块电池下次“充满可用”的时间点。
- 初始所有电池满电:
nextFull[i] = 0 - 当前时间
cur - 在
cur时刻,所有满足nextFull[i] <= cur的电池都可用 - 用完电池后更新:
nextFull[i] = cur + recharge[i]
为了尽量减少使用电池数,直觉上每次优先用 当前可用里 capacity 最大 的那块。
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,以及一系列操作 operations:
[0, index, val]:更新secondary[index] = val[1, targetSum]:查询满足primary[i] + secondary[j] == targetSum的 pair 数量
其中:
primary固定不变secondary会频繁更新
为什么暴力会超时?
如果你每次 query 都遍历两数组:
O(n*m)直接爆炸
即使你把 primary 先做成 hashmap,再遍历 secondary:
- 每次 query 还是
O(n + m),操作多也扛不住
正解:频率表 + 动态维护
这是面试官最爱给的暗示:
- “一边 fixed / 一边 dynamic”
做法:
- 对
primary做freqA(固定) - 对
secondary做freqB(会变) - 更新时:
- 把旧值从
freqB里减掉 - 把新值加进去
- 把旧值从
- 查询时:
- 枚举
freqA里的 distinct keya - 累加
freqA[a] * freqB[targetSum - a]
- 枚举
时间复杂度(关键优势):
- 更新:
O(1) - 查询:
O(distinct(primary))
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,获得真题。