8. 最大子列和

问题描述:对给定数组A,寻找A的和最大的非空连续子数组。

输入格式:输入的第一行包括一个整数n,代表数组中的元素个数,接下来的一行包含n个整数(可以包含负数),以空格分隔。

输出格式:一个整数,表示最大的连续子数组的和。

样例输入:

9

2  4  -7  5  2  -1  2  -4  3

样例输出:

8

思路:1.分治法

  分解:把数组从中间位置划分成两个子数组。

  解决:使用分治法递归地求解这两个子数组的最大子数组。当规模缩小到子数组长度为1时,直接返回该元素的值。

  合并:求解跨越两个子数组的最大子数组,即跨越这个相邻子数组合成的数组中点的最大子数组,并与之前得到的结果进行比较,选取和最大者。

  时间复杂度:O(NlogN)

Code:

#include<iostream>
#include<vector>
using namespace std;
vector<int> a;
int n;
int solve(int L, int R){
    if (L == R) return a[L];
    int maxL = 0, maxR = 0, maxMid = 0;
    int mid = (L + R) / 2;
    int sumL = 0, sumR = 0, maxSumL = 0, maxSumR = 0;
    maxL = solve(L, mid);
    maxR = solve(mid+1, R);
    for (int i = mid; i >= 0; i--){
        sumL += a[i];
        if (sumL > maxSumL)
            maxSumL = sumL;
    } 
    for (int i = mid+1; i <= R; i++){
        sumR += a[i];
        if (sumR > maxSumL)
            maxSumL = sumR;
    }
    return max(max(maxL, maxR), maxSumL+maxSumR);
}

int main(){
    scanf("%d", &n);
    a.resize(n);
    for(int i = 0; i < n; i++)
        scanf("%d", &a[i]);
    cout << solve(0, n-1);
    return 0;
}

  2.动态规划

  dp[n] 表示以第n个数为结尾的最大子列和。

  dp[n] = max(0, dp[n-1]) + a[n]。

  时间复杂度为O(N)

  

#include<iostream>
using namespace std;
int n;
int main(){
    scanf("%d", &n);
    int x, sum = 0, maxSum = 0;
    for(int i = 0; i < n; i++){
        cin >> x;
        sum += x;
        if (sum > maxSum) maxSum = sum;
        else if (sum < 0) sum = 0;
    } 
    cout << maxSum;
    return 0;
}

 

posted @ 2019-10-19 21:17  莫莫君不恋爱  阅读(198)  评论(0编辑  收藏  举报