给定一个数组A我想找到一个段的第一个索引,其中所选段的平均值是其他段中的最小值。
Example: A = {1, 1, 3, 4, 5, 6, 7}
segment (1,2) = {1,1} ==> avg = 1+1/2 = 1
segment (1,3) = {1,1,3} ==> avg = 1+1+3/3 = 1.6
etc..
________________________________________________
input: {1, 1, 3, 4, 5, 6, 7}
output: 1
说明:最小平均值为1
因此输出应该是该段的第一个索引(1,2),在这种情况下为1
。
我目前的代码如下:
int getIndex(vector<int> A)
{
if (A.size() <= 2) return 0; /*if array is a single segment then index:0 is the answer.*/
vector<int> psums; psums.push_back(A[0]);
for(size_t i =1; i< A.size(); i++)
{
psums.push_back(psums[i-1] + A[i]);
}
float min = 1111111111; /*assuming this is a max possible numb*/
int index;
float avg;
for(size_t i =1; i< psums.size(); i++)
{
for(size_t j = 0; j < i; j++)
{
avg = (float)((psums[i] - psums[j]) / (i-j+1));
if (min > std::min(min, avg))
{
min = std::min(min, avg);
index = j;
}
}
}
return index;
}
此代码返回不正确的值。想法?
答案 0 :(得分:1)
好的,我有一些时间,所以这里是你希望寻找的代码(并希望它也可以编译 - 我没有机会在我发布它之前测试,所以给我事后几分钟检查 - 好吧,现在用gcc-4.7.2编译:
#include<vector>
#include<tuple>
#include<functional>
#include<algorithm>
#include<iostream>
#include <numeric>
size_t getIndex(const std::vector<int>& A) //pass by const ref instead of by value!
{
size_t n=A.size();
//define vector to store the averages and bounds
std::vector<std::tuple<size_t, size_t, double> > store;
for(size_t iend=0;iend<n;++iend)
for(size_t ibegin=0;ibegin<iend;++ibegin) //changed from <= to < as segments need to have length >=2
{
//compute average: sum all elements from ibegin to iend to 0.0, cast to double and divide by the number of elements
double average=static_cast<double>(std::accumulate(A.begin()+ibegin, A.begin()+iend,0.0))/(iend-ibegin+1);
//store the result with bounds
store.push_back(std::make_tuple(ibegin,iend,average));
}
//define lambda which compares the tuple according to the third component
auto compare_third_element=[](const std::tuple<size_t,size_t,double> &t1, const std::tuple<size_t,size_t,double> &t2){return std::get<2>(t1)<std::get<2>(t2);};
//now find the iterator to the minimum element
auto it=std::min_element(store.begin(),store.end(),compare_third_element);
//print range
//std::cout<<"("<<std::get<0>(*it)<<","<<std::get<1>(*it)<<")"<<std::endl;
return std::get<0>(*it);
}
int main()
{
std::vector<int> A={1,1,2,3,4,5,6,7};
std::cout << getIndex(A);
return 0;
}
警告:可能会有多个段产生最小平均值。对于上面的示例,该函数在屏幕上打印段(0,0)
,因为它包含最小元素1
。如果要获取所需的范围,请使用std::nth_element
访问下一个条目,或更改比较功能(例如,为更长的元组提供更高的优先级)。
答案 1 :(得分:0)
(psums[i] - psums[j])
和(i-j+1)
都是整数。它们之间的区别是所谓的,不完整的分裂,因此你只得到结果的整个部分。将其中一个元素转换为float或double,如下所示:
(float)(psums[i] - psums[j])/(i-j+1)
a/b
中的分割类型取决于a
和b
的类型,而不是您输入结果的变量!
注意: std::min(min, avg)
不是必需的,而只是使用:avg
修改: psum[i]-psum[j]=A[i]+A[i-1]+...+A[j+1]
因为psum[i]=A[0]+A[1]+A[2]+..+A[i]
所以
avg
- 行应该如下所示:
avg=(float)(psums[i] - psums[j] + A[j])/(i-j+1)