若数组总和不能被3整除,直接返回false;空数组或长度小于3也返回false;否则用前缀和两次遍历找两个分割点i、j,使三段和相等。

先判断总和是否能被3整除
如果数组总和 sum 不能被3整除,直接返回 false —— 这是最快也最常被跳过的前提。很多人一上来就找分割点,结果白忙活。
-
sum % 3 != 0时,不可能划分为三个等和部分,立刻退出 - 注意整数溢出:用
long long存总和,尤其当数组元素可能为大整数或含负数时 - 空数组或长度小于3的数组,直接返回
false
用前缀和 + 两次遍历定位分割下标
目标是找到两个下标 i 和 j(满足 0 ≤ i ),使得:<br>— <code>sum(arr[0..i]) == target
— sum(arr[i+1..j]) == target
— 剩余部分自动为 target
- 先算出
target = sum / 3 - 第一次遍历累加前缀和,遇到前缀和等于
target就记下第一个合法结束位置i(注意:i必须 ≤n-3,否则后面没空间放两段) - 第二次遍历从
i+1开始,继续累加,找第二个等于target的区间终点j(要求j ≤ n-2) - 不需要真的切分数组或拷贝子数组,纯指针/下标操作即可
处理全零或负数导致的多解歧义
当 target == 0 时(比如数组全是0,或正负抵消),会出现多个满足前缀和为0的位置,但并非所有组合都合法 —— 必须确保三段非空且连续。
- 例如
[0,0,0,0]:虽然前缀和在索引0、1、2、3处都是0,但只允许选前两个“首次达标”的分割点(如 i=0, j=1),使三段为[0], [0], [0,0]—— 不对;正确是 i=0, j=1 →[0],[0],[0,0]仍错;实际要 i=0, j=1 不行,得 i=0, j=2 →[0],[0],[0,0]还是错……本质是必须保证第三段存在且非空,所以j最大只能是n-2,且第一段末尾i最大只能是n-3 - 更稳的做法:找到第一个
i满足prefix[i] == target && i ,再从 <code>i+1开始找第一个j满足prefix[j] - prefix[i] == target && j - 避免用「统计前缀和等于 target 的次数 ≥ 2」这种宽松判断——它会把
[1,-1,1,-1,1,-1](sum=0, target=0)误判为 true,但实际上无法划成三个连续非空段
C++ 实现中容易漏掉的边界检查
写完逻辑后,90% 的 WA(Wrong Answer)来自下标越界或段长度为0。
- 定义
long long target = sum / 3;后,别忘了if (sum % 3 != 0)已提前返回,所以此处除法安全 - 循环里用
i 限制第一段结尾(留至少2个元素给后两段),而不是 <code>i - 第二段结尾
j要满足j (第三段至少1个元素) - 推荐用
for (int i = 0; i 和 <code>for (int j = i + 1; j ,语义清晰不易错 - 如果用单次遍历优化(边扫边计数),需额外记录是否已找到第一段,否则可能把同一段重复计入
实际写的时候,最麻烦的不是算法逻辑,而是把「三段非空」「下标不越界」「target为0时的行为」这三件事同时约束住。多数人卡在测试用例 [0,0,0,0] 或 [1,-1,0,0,-1,1] 上,问题往往不出在思路,而在某一处 写成了 <code>,或者忘了 <code>j 至少要比 i+1 大。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











