Go中一维前缀和需用make([]int, n+1)创建,prefix[0]=0,递推prefix[i]=prefix[i-1]+nums[i-1],使区间[l,r]和为prefix[r+1]-prefix[l];二维同理,prefixi表示前i行j列和,递推公式为“上+左−左上+当前”,查矩形用prefixr2+1−prefixr1−prefixr2+1+prefixr1。

Go 语言里怎么写一维前缀和数组
直接用 make([]int, n+1) 开个长度为 n+1 的切片,索引从 0 开始,prefix[0] = 0,然后遍历原数组,递推填值:prefix[i] = prefix[i-1] + nums[i-1]。这样设计是为了让区间 [l, r](闭区间)的和能用 prefix[r+1] - prefix[l] 一步算出,不用额外判断边界。
常见错误是把 prefix 长度开成 n,结果 r+1 越界;或者初始化时漏掉 prefix[0] = 0,导致所有查询偏移错位。
- 原数组下标从
0开始,前缀和数组下标对应「前 i 个元素之和」,所以必须多留一位 - 如果后续要频繁查区间和,且原数组不变,这个预处理 O(n) 换来每次 O(1) 查询,非常划算
- 注意:Go 切片底层数组可能被复用,别把
prefix直接传给会修改它的函数,除非你明确知道在改什么
二维前缀和怎么初始化(matrix[i][j] 对应 prefix[i+1][j+1])
二维本质是一维的推广,核心仍是补零对齐:定义 prefix 为 [][]int,尺寸 (m+1) x (n+1),其中 prefix[i][j] 表示从 matrix[0][0] 到 matrix[i-1][j-1] 的子矩阵和。递推公式是:prefix[i][j] = prefix[i-1][j] + prefix[i][j-1] - prefix[i-1][j-1] + matrix[i-1][j-1]。
最容易踩的坑是行列下标没统一偏移,比如混用 i 和 i-1 导致加错位置,或者忘记减去重叠部分 prefix[i-1][j-1],结果整个矩阵和翻倍。
- 记住口诀:「上 + 左 − 左上 + 当前」,顺序不能乱
- 查矩形
[r1, c1] ~ [r2, c2](闭区间)时,用prefix[r2+1][c2+1] - prefix[r1][c2+1] - prefix[r2+1][c1] + prefix[r1][c1] - 如果矩阵很大且稀疏,前缀和反而浪费内存;此时考虑离散化 + 树状数组更合适
前缀和能和 slice 原地操作共存吗
不能直接复用原数组空间做前缀和,除非你确定后续再也不需要原始值。Go 的 []int 是引用类型,一旦你把 nums 改成前缀形式,所有依赖原始值的地方都会出错——比如你后来还想取 nums[3],它已经不是原来那个数了。
性能上,额外分配 O(n) 空间几乎无代价,但语义混乱的成本极高。编译器不会帮你检查这种逻辑错误,运行时也不会报错,只有业务结果不对才暴露问题。
- 永远新建
prefix变量,别覆盖原nums - 如果内存极度敏感(如嵌入式场景),可考虑用
unsafe手动管理,但这属于例外,不是默认做法 - 单元测试里务必覆盖
l=0、r=n-1、单点查询等边界 case,否则很容易漏掉偏移错误
遇到负数或大整数,前缀和还安全吗
Go 的 int 类型本身不提供溢出检测,所以如果原数组含大整数或累加过程超限,prefix 值会静默翻转,后续所有区间查询都错。这不是算法问题,是数据表示问题。
没有银弹,但可以按需选型:int64 覆盖绝大多数场景;若真要处理超大和,得换 big.Int,不过性能下降明显,而且所有加减逻辑都要显式调用方法。
- 上线前用极端数据跑一遍,比如全填
math.MaxInt64,看会不会崩 - 如果业务允许误差,可考虑用 float64 存前缀和(仅限非精确统计场景)
- 静态分析工具如
go vet或staticcheck不会报这类溢出,得靠测试或手动审查
事情说清了就结束。前缀和本身很简单,难的是每次写的时候都记得补零、对齐、不复用、测边界——这些地方不靠脑子记,靠肌肉反应。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











