多个阵列段的最小平均值

时间:2014-05-22 11:26:06

标签: c++ arrays algorithm

给定一个数组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;
}

此代码返回不正确的值。想法?

2 个答案:

答案 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中的分割类型取决于ab 的类型,而不是您输入结果的变量!

注意: 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)