问题描述
vector<int> nums={1,12,-5,-6,50,3};
int k=4;
int n=nums.size();
for(int i=0;i<=n-k;i++)
cout<<accumulate(nums.begin()+i,nums.begin()+i+k-1,0)<<" ";
问题是为什么[1,12,-5,-6]的总和为8,应为2 =(1 + 12-5-6)?
与1相同,应该为51 =(50 + 12-5-6),并且
是否与39相同,应该是42 =(50 + 3-6-5)?
解决方法
如果您实际上做了accumulate
的操作-依次添加-并查看每个部分结果,您将看到
1 + 0 = 1
1 + 12 = 13
13 + -5 = 8
8 + -6 = 2
12 + 0 = 12
12 + -5 = 7
7 + -6 = 1
1 + 50 = 51
-5 + 0 = -5
-5 + -6 = -11
-11 + 50 = 39
39 + 3 = 42
在这一点上,您可能会发现accumulate
的结果是前三个数字的总和,而不是四个。
然后,您大声惊叹accumulate
中存在一个错误,使它无视最后一个元素。
然后,您查看文档,发现范围的末尾是“最后一个元素之后”,因此您的最终迭代器nums.begin() + i + 4 - 1
表示其前面的元素(即*(begin() + i + 2)
,begin() + i
中的第三个元素是范围内 中的最后一个元素。
标准库中的所有迭代器范围(和索引间隔)都以这种方式半开放。
解决方案是从最终迭代器中删除-1
。
如果您的假设是std::accumulate
不按照常规方式处理负数,请直接进行测试
#include <iostream>
#include <vector>
#include <numeric>
int main() {
std::vector<int> nums={1,12,-5,-6,50,3};
std::cout << std::accumulate(nums.begin(),nums.begin() + 4,0);
}
输出为2,对应于1 + 12 - 5 - 6
。
问题出在您的代码中;并在您的迭代器中添加。具体来说,std::accumulate
的前两个参数都相对于nums.begin()
:您需要从第二个参数中删除-1
。
std::accumulate
的第二个参数是位置紧挨着要处理的元素。
-1
中的nums.begin()+i+k-1
正在阻止处理最后一个要处理的元素,因此应将其删除。