动态和是生成新数组,各元素为原数组从首项到该项的累加和,如{1,2,3,4}→{1,3,6,10};不可用std::accumulate重复计算以免O(n²),推荐原地更新或std::partial_sum,注意输入输出迭代器、溢出及const引用问题。

什么是动态和,为什么不能直接用 std::accumulate
动态和不是求总和,而是生成一个新数组,其中每个元素是原数组从开头到当前位置的所有元素之和。比如 {1,2,3,4} 的动态和是 {1,3,6,10}。很多人第一反应是用 std::accumulate 对每个位置重复计算,但这会导致 O(n²) 时间复杂度——每算一个位置都要从头加一遍,完全没必要。
最常用且安全的写法:原地更新 + 循环遍历
只要原数组可修改,就直接在原数组上累加,空间 O(1),时间 O(n),也避免了额外内存分配。注意从索引 1 开始,因为第 0 个元素就是它自己:
for (int i = 1; i < n; ++i) {
nums[i] += nums[i - 1];
}- 必须确保
n > 0,否则i = 1会越界;空数组要提前判断 - 如果输入是
const std::vector<int>&,就不能原地改,得新建 vector - 整数溢出风险:如果元素很大、数组很长,
int可能溢出,必要时换成long long
用 std::partial_sum 的注意事项
std::partial_sum 是标准库提供的正确工具,但容易用错参数顺序和迭代器范围:
std::vector<int> result(nums.size()); std::partial_sum(nums.begin(), nums.end(), result.begin());
- 第三个参数是输出起始位置,不是容器本身;漏写或写成
result(而非result.begin())会编译失败 - 如果想原地计算,可以传
nums.begin()作输出,但前提是输入输出范围不重叠(这里刚好满足) - 默认用
operator+,支持自定义二元操作符,比如用乘法做“动态积”,但很少用
返回新 vector 的函数封装常见坑
封装成函数时,最容易被忽略的是 const 引用输入与返回值生命周期问题:
立即学习“C++免费学习笔记(深入)”;
std::vector<int> runningSum(const std::vector<int>& nums) {
if (nums.empty()) return {};
std::vector<int> res = nums; // 必须拷贝,不能返回局部引用
for (int i = 1; i < res.size(); ++i) {
res[i] += res[i-1];
}
return res;
}- 别写
return std::move(res)——现代 C++ 编译器会自动 RVO,手动 move 反而可能禁用优化 - 如果函数声明返回
const std::vector<int>&,那就彻底错了:返回局部变量引用是未定义行为 - 用
std::size(nums)替代nums.size()可兼容 C 风格数组,但 vector 场景下差别不大
真正麻烦的是边界条件和类型匹配——比如输入是 std::vector<unsigned int>,输出却用了 int,负数不会出现,但溢出行为更隐蔽。


















