您的位置:首页 > 其它

算法设计技术

2015-10-03 22:27 274 查看
算法设计技术

问题:问题的输入是具有n个浮点数的向量x,输出是输入向量的任何连续子向量中的最大和。例如,如果输入向量包含下面10个元素:31,-41,59,26,-53,58,97,-93,-23,84

代码:

float arr[] = { 31, -41, 59, 26, -53, 58, 97, -93, -23, 84 };

// 立方算法  时间复杂度为T(n) = O(n^3)

float CubeMaxSubSum(const float *arr, const int N , int &begin , int &end)

{

    float maxsofar = 0 ;

    for (int i = 0; i < N; i++)

    {

        for (int j = i; j < N; j++)

        {

            float sum = 0;

            for (int k = i; k <= j; k++)

            {

                sum += arr[k];

            }

            if (sum > maxsofar)

            {

                maxsofar = sum;

                begin = i;

                end = j;

            }

        }

    }

    return maxsofar;

}

// 平方算法1  时间复杂度T(n)=O(n^2);

float SquareMaxSubSum(const float *arr, const int N, int &begin, int &end)

{

    float maxsofar = 0;

    for (int i = 0; i < N; i++)

    {

        float sum = 0;

        for (int j = i; j < N; j++)

        {

            sum += arr[j];

            if (sum > maxsofar)

            {

                maxsofar = sum;

                begin = i;

                end = j;

            }

        }

    }

    return maxsofar;

}

#define N 10

// 平方算法2  时间复杂度T(n)=O(n^2);

float SquareTMaxSubSum(const float *arr, const int n, int &begin, int &end)

{

    /*

     * 下面3行代码解决 cumarr[-1] 的问题

     */

    float realsum[N + 1] = { 0 };

    float *cumarr = realsum + 1;

    cumarr[-1] = 0;

    for (int i = 0; i < n; i++)

    {

        cumarr[i] = cumarr[i - 1] + arr[i];

    }

    float maxsofar = 0;

    for (int i = 0; i < n; i++)

    {

        float sum = 0;

        for (int j = i; j < n; j++)

        {

            sum = cumarr[j] - cumarr[i-1];

            if (sum > maxsofar)

            {

                maxsofar = sum;

                begin = i;

                end = j;

            }

        }

    }

    return maxsofar;

}

float max(float a, float b)

{

    return a > b ? a : b;

}

// 分治算法 时间复杂度T(n)=O(nlogn);

/************************************************************************/

/*

* 算法说明:

*(1)当所有输入都是正数时,最大子向量就是整个输入向量

*(2)当所有输入都是负数时,最大子向量是空向量,和为0

*(3)当前处理情况是,输入序列有正有负

*/

/************************************************************************/

float DivideMaxSubSum(const float *arr, int left , int right)

{

    if (left > right)

        return 0;

    if (left == right)

        return 0 > arr[left] ? 0 : arr[left];

    int middle = (left + right) / 2;

    float lmax = 0, sum = 0;

    for (int i = middle; i >= left; i--)

    {

        sum += arr[i];

        lmax = lmax > sum ? lmax : sum;

    }

    float rmax = 0;

    sum = 0;

    for (int j = middle + 1; j <= right; j++)

    {

        sum += arr[j];

        rmax = rmax > sum ? rmax : sum;

    }

    return max(max((lmax + rmax), DivideMaxSubSum(arr , left, middle)), DivideMaxSubSum(arr , middle + 1, right));

}

// 扫描算法 时间复杂度T(n)=O(n);

float ScanMaxSubSum(const float *arr, const int n )

{

    float maxSoFar = 0, maxEndInHere = 0;

    //该问题的关键在于maxEndInHere变量,它是结束位置i-1之前的最大子向量之和

    for (int i = 0; i < n; i++)

    {

        maxEndInHere = max(maxEndInHere + arr[i], 0);

        maxSoFar = max(maxSoFar, maxEndInHere);

    }

    return maxSoFar;

}

int main(int argc, char *argv[])

{

    QCoreApplication a(argc, argv);

    int begin = -1, end = -1;

    int k = ScanMaxSubSum(arr, 10);

    printf("k = %d\n", k);

    return a.exec();

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: