题目重点:按维数笛卡尔积生成下标,比较递归与迭代写法,处理空维、零维和 API 调用成本。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 每维大小为非负整数,索引从 0 到 d-1;get 为确定性读操作。任一维为 0,则没有元素、总和 0;零维 [] 当标量调用 get([]) 一次,这一点题目未说明,必须问接口。
- 训练代码不预设元素一定是 int 以外的类型,但总和需支持加法;题目函数注解 int,实际类型当轮确认。
解题路线
- 读取 dims 一次,生成每个维度 range(d) 的笛卡尔积。对每组索引调用 get(list(indices)),累加返回值。
- 递归写法可维护一个长度 D 的 index buffer,在第 k 维循环 0…dims[k)-1,第 D 层调用 get;迭代写法可把索引当 mixed-radix counter,逐维进位。两者都访问恰好所有元素一次。
- 如果 get 是远程 API,算法仍需 P=∏dims 次逻辑读取,但可以询问批量/切片接口并按相邻维度批读,避免 P 次网络 RTT;并行读要遵守限流。
- dims 很长时递归可能超栈,训练代码用迭代 product。长度为 0 的维度是空数组,不应访问 get。
手动走一遍
dims=[2,2,3] 产生 12 组索引,从 [0,0,0] 到 [1,1,2],每个 get 一次后求和。dims=[2,0,3] 无任何合法索引,返回 0;dims=[] 在训练约定下读唯一标量 get([])。
Python 参考实现
下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。
代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。
from itertools import product
def array_sum(multidim_array) -> int:
"""Requires getDims() and get(indices). Empty dimensions have no cells."""
dims = multidim_array.getDims()
if any(d < 0 for d in dims):
raise ValueError("negative dimension")
total = 0
for indices in product(*(range(d) for d in dims)):
total += multidim_array.get(list(indices))
return total
复杂度
D 维、P=∏dᵢ 个元素:O(PD) 下标生成/复制时间加 P 次 get,迭代工作空间 O(D)(不计 API 内部缓冲)。如果传入 list 每次复制 D 项,不能只说 O(P)。8,000 组随机形状与独立线性存储求和对照通过。
易错点与追问
容易失分的边界
- 把维数之和当元素个数。
- 忘记某一维为 0 时数组为空。
- 重复调用 getDims 造成远端开销。
- 在循环复用可变 indices 对象而异步 get 尚未消费。
- 未核对零维代表标量还是空集合。
继续深挖
- 若 get 有网络延迟,如何批量读取?
- 稀疏数组只有非零位置可枚举时还遍历全部 P 吗?
- 如果维度特别多导致 P 溢出,如何防护?
- 负维或动态维度变化时如何处理?
