Loading

计蒜客_最大子阵列

主要用到的思想:

对于数组A[1..n],如果已知其子数组A[1..j]的最大子阵列,则可以在常数时间内获取A[1..j+1]的最大子数组,具体思路如下:A[1..j+1]的最大子数组(记为max_j+1),要么(不包含A[j+1])(即,A[1..j]的最大子数组(记为max_j)),要么是包含的A[j+1]的局部最大子数组(暂时叫做maybeMax_j+1)。
前一种情况容易获取,对于第二种情况,假设可以维护一个包含A[j]的A[1..j]的最大子数组的值(暂时叫做 maybeMax_j),那么包含A[j+1]的A[1..j+1]的最大子数组(暂时叫做maybeMax_j+1)要么是A[j+1]+maybeMax_j,要么是 A[j+1],证明如下:

可以将maybeMax_j+1分为两类包含包含maybeMax_j的和不包含maybeMax_j的。
(1)对于包含A[1..j]中元素的情况,
假设,maybeMax_j为A[k..j],for any k'(k' != k,1<=k'<=j),A[k'..j]<Ak..j,也即是A[k..j]+A[j+1]>A[k'..j]+A[j+1],所以包含A[1..j]中元素的maybeMax_j+1待选项为Ak..j+1
(2)不包含A[1..j]中元素的情况,
即,A[j+1];
对于两种情况的选择,即代码中的if (a[i] + maybeMax > a[i]).
对于A[1..j+1]的max_j+1,要么是maybeMax_j+1,要么是max_j,对于两种情况的选择,即代码中if (maybeMax > max).
具体变量所指所指如图:

由此可知,由maybeMax_j经过常数时间可以得出maybeMax_j+1;进一步,由max_j可以在常数时间得出max_j+1;
初始情况下,易得,max_j=A[1],maybeMax_j=A[1].
整个算法时间复杂度为O(n).具体代码如下:

#include<iostream>
using namespace std;
int getAns(int *a, int len) {
    int maybeMax = a[0];
    int max = a[0];
    for (int i = 1; i < len; ++i) {
        if (a[i] + maybeMax > a[i]) {
            maybeMax = a[i] + maybeMax;
        }
        else {
            maybeMax = a[i];
        }
        if (maybeMax > max) {
            max = maybeMax;
        }
    }
    return max;
}
void maxSubArray() {
    int a[1000];
    int n;
    cin >> n;
    for (int i = 0; i < n; ++i) {
        cin >> a[i];
    }
    cout<<getAns(a, n)<<endl;
}
int main()
{
    maxSubArray();
    return 0;
}

算法导论分治法那一章,使用分治法,时间复杂度为 \(O(n\lg n)\).并且课后有相似习题,介绍了上面的这种方法。
实现代码

posted @ 2017-08-19 20:17  lif323  阅读(366)  评论(0)    收藏  举报