最大子序列和问题

来源:互联网 发布:vb中case是什么意思 编辑:程序博客网 时间:2024/05/16 23:57

问题描述:
给定一整数序列A1, A2,... An (可能有负数),求A1~An的一个子序列Ai~Aj,使得Ai到Aj的和最大。只要求出最大子序列的和,不必求出最大的那个序列。
例如:
整数序列-2, 11, -4, 13, -5, 2, -5, -3, 12, -9的最大子序列的和为21。


下面是C语言实现算法:
算法一:

//穷举算法 复杂度O(N^2)int MaxSubSum1(int array[], int len) {    int v, maxSum = array[0];    for (int i = 0; i < len; i++) {        v = 0;        for (int j = i; j < len; j++) {            v += array[j];            if (v > maxSum) {                maxSum = v;            }        }    }    return maxSum;}

对于这个问题,最简单也是最容易想到的那就是穷举所有子序列的方法。


//穷举算法 也求出了最大的那个子序列int MaxSubSum2(int array[], int len) {    int v, maxSum = array[0];    int start = 0; //最大子序列起始索引值    int stop = 0;  //最大子序列终止索引值    for (int i = 0; i < len; i++) {        v = 0;        for (int j = i; j < len; j++) {            v += array[j];            if (v > maxSum) {                maxSum = v;                start = i;                stop = j;            }        }    }        //最大子序列    for (int i = start; i <= stop; i++) {        int v = array[i];        printf("%d ", v);    }    return maxSum;}


算法二:

//线性算法 复杂度O(N)int MaxSubSum3(int array[], int len) {    int thisSum = 0, maxSum = 0;    for (int i = 0; i < len; i++) {        thisSum += array[i]; //向右累加        if (thisSum > maxSum)            maxSum = thisSum; //发现更大和则更新当前结果        else if (thisSum < 0) //如果当前子列和为负            thisSum = 0; //则不可能使后面的部分和增大,抛弃之    }    return maxSum;}


//线性算法 求出了最大的那个子序列int MaxSubSum4(int array[], int len) {    int thisSum = 0, maxSum = 0;    int start = 0, thisStart = 0, stop = 0;    for (int i = 0; i < len; i++) {        thisSum += array[i];        if (thisSum > maxSum) {            maxSum = thisSum;            start = thisStart;            stop = i;        }        else if (thisSum < 0) {            thisSum = 0;            thisStart = i + 1;        }    }    //最大子序列    for (int i = start; i <= stop; i++) {        int v = array[i];        printf("%d ", v);    }        return maxSum;}

算法二是许多聪明算法的典型:运行时间是明显的,但是正确性则很不明显(也就是不容易理解)。



0 0
原创粉丝点击