给你一个数组,求一个k值,使得前k个数的方差 + 后面n-k个数的方差最小 。

问题:给你一个数组,求一个k值,使得前k个数的方差 + 后面n-k个数的方差最小 ,时间复杂度为o(n)。

思路:申明两个数组分别用来存储从左侧开始计算的方差,和从右侧开始计算的方差,最后将两个数组错一位相加,取和值最小的位点返回。

程序实现:

#include <iostream>
#include<stdio.h>
#include<string.h>


using namespace std;

int minVar(float *a,int n)
{
    float *left=new float[n];
    float *right=new float[n];
    float leftsum=0;
    float rightsum=0;
    float leftSquareSum=0;
    float rightSquareSum=0;
    memset(left,0,n);
    memset(right,0,n);
    for(int i=0;i<n;i++)
    {
        leftsum+=a[i];
        leftSquareSum+=a[i]*a[i];
        left[i]=leftSquareSum/(i+1)-(leftsum/(i+1))*(leftsum/(i+1));
    }
    /*
    for(int i=0;i<n;i++)
    {
        cout<<left[i]<<endl;
    }*/

    for(int i=n-1;i>=0;i--)
    {
        rightsum+=a[i];
        rightSquareSum+=a[i]*a[i];
        right[i]=rightSquareSum/(n-i)-(rightsum/(n-i))*(rightsum/(n-i));
    }
    /*
    for(int i=0;i<n;i++)
    {
        cout<<right[i]<<endl;
    }
    */
    for(int i=0;i<n-1;i++)
    {
        left[i]+=right[i+1];
    }

    /*
    cout<<endl;
    for(int i=0;i<n;i++)
    {
        cout<<left[i]<<endl;
    }
   */

    float minvar=left[0];
    int pos=0;
    for(int i=0;i<n;i++)
    {
        if(minvar>left[i])
        {
            minvar=left[i];
            pos=i;
        }
    }
    cout<<"minVar:"<<minvar<<endl;
    return (pos+1);
}

int main()
{
    float a[10]={1,2,3,4,5,11,12,13,14,15};
    cout<<"pos:"<<minVar(a,10)<<endl;
    return 0;
}

输出结果:

minVar:4
pos:5


猜你喜欢

转载自blog.csdn.net/u013069552/article/details/80992544