最大连续和

Posted 扶芥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最大连续和相关的知识,希望对你有一定的参考价值。

问题:给出一个长度为n的序列a1,a2,a3....an,求最大连续和,即找到1<=i<=j<=n,是的ai+...+aj最大

1.暴力枚举

int sum = 0;
    int max = 0;
    for (int i = 0; i < n; i++) {
        for (int j = i; j < n; j++) {
            sum = 0;
            for (int k = i; k <= j; k++)
                sum += a[k];
            if (max < sum)
                max = sum;
        }
    }

T(n)=n(n+1)(n+2)/6=O(n3)

 

2.递推

利用前缀   

  int s[100];
    int max = 0;
    s[0] = a[0];
    for (int i = 1; i < n; i++)
        s[i] = s[i - 1] + a[i];
    for (int i = 0; i < n; i++) {
        for (int j = i; j < n; j++) {
            int t = i == 0 ? s[j] : s[j] - s[i - 1];
            max = Max(max, t);
        }
    }

 

T(n)=O(n2)

3.分治法

   1)划分:把序列分成元素个数尽量相等的两半;

   2) 递归求解:分别求出完全位于左半或者完全位于右半的最佳序列

   3)合并:求出起点位于左半,终点位于右半的最大连续和序列,并和子问题的最优解比较

   关键在于“合并”步骤,既然起点位于左半,终点位于右半,我们可以认为地把这样的序列分成两部分,

   然后独立求解:先寻找最佳起点,然后再寻找最佳终点。

int maxsum3(int a[], int left, int right) {    //左闭右开
    int i, m, v, L, R, max;
    if (right - left == 1) return a[left];
    m = left + (right - left) / 2;              //第一步,划分成[left,m),[m,right)
    max = Max(maxsum3(a, left, m), maxsum3(a, m, right));
                                                           //第二步,递归求解

                                                           //第三步,合并
    v = 0; L = a[m - 1];                      
    for (i = m - 1; i >= left; i--)
        L = Max(L, v += a[i]);
    v = 0; R = a[m];
    for (i = m; i < right; i++)
        R = Max(R, v += a[i]);
    return Max(max, L + R);
}

// 练习.cpp: 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<time.h>
#include<windows.h>

using namespace std;

int Max(int a, int b) {
	return a > b ? a : b;
}

//暴力枚举

int maxsum1(int a[], int n) {
	int sum = 0;
	int max = 0;
	for (int i = 0; i < n; i++) {
		for (int j = i; j < n; j++) {
			sum = 0;
			for (int k = i; k <= j; k++)
				sum += a[k];
			if (max < sum)
				max = sum;
		}
	}
	return max;
}

//递推前缀

int maxsum2(int a[], int n)
{
	int s[100];
	int max = 0;
	s[0] = a[0];
	for (int i = 1; i < n; i++)
		s[i] = s[i - 1] + a[i];
	for (int i = 0; i < n; i++) {
		for (int j = i; j < n; j++) {
			int t = i == 0 ? s[j] : s[j] - s[i - 1];
			max = Max(max, t);
		}
	}
	return max;
}

//分治法
      
int maxsum3(int a[], int left, int right) {    //左闭右开
	int i, m, v, L, R, max;
	if (right - left == 1) return a[left];
	m = left + (right - left) / 2;             //第一步,划分成[left,m),[m,right)
	max = Max(maxsum3(a, left, m), maxsum3(a, m, right));
	                                           //第二步,递归求解
	v = 0; L = a[m - 1];                       //第三步,合并
	for (i = m - 1; i >= left; i--)
		L = Max(L, v += a[i]);
	v = 0; R = a[m];
	for (i = m; i < right; i++)
		R = Max(R, v += a[i]);
	return Max(max, L + R);
}

int main()
{
	int n;
	int a[100];
	cin >> n;
	for (int i = 0; i < n; i++) {
		cin >> a[i];
	}
	int s1 = maxsum1(a, n);
	int s2 = maxsum2(a, n);
	int s3 = maxsum3(a, 0, n);
	cout << s1 << endl;
	cout << s2 << endl;
	cout << s3 << endl;
	system("pause");
	return 0;
}

 

以上是关于最大连续和的主要内容,如果未能解决你的问题,请参考以下文章

写写代码系列013:剑指offer题目——连续子数组的最大和(动态规划)

算法小总结最大连续子序列和最大连续子矩阵的关系与实现

求连续序列的最大子序列和

最大连续子序列问题(tyvj1305)

最大子阵列/连续数组的最大和

最大连续区间和问题