经典算法问题 - 最大连续子数列和

暴力 O(n方)

#include <stdio.h>

//N是数组长度,num是待计算的数组,放在全局区是因为可以开很大的数组
int N, num[1024];

int main()
{
    //输入数据
    scanf("%d", &N);
    for(int i = 1; i <= N; i++)
        scanf("%d", &num[i]);
    
    int ans = num[1]; //ans保存最大子序列和,初始化为num[1]能保证最终结果正确
    //i和j分别是枚举的子序列的起点和终点,k所在循环计算每个子序列的和
    for(int i = 1; i <= N; i++) {
        for(int j = i; j <= N; j++) {
            int s = 0;
            for(int k = i; k <= j; k++) {
                s += num[k];
            }
            if(s > ans) ans = s;
        }
    }
    printf("%d\n", ans);

    return 0;
}

前缀和优化O(n*n)

#include <stdio.h>

//N是数组长度,num是待计算的数组,sum是数组前缀和,放在全局区是因为可以开很大的数组
int N, num[16384], sum[16384];

int main()
{
    //输入数据
    scanf("%d", &N);
    for(int i = 1; i <= N; i++)
        scanf("%d", &num[i]);
    
    //计算数组前缀和
    sum[0] = 0;
    for(int i = 1; i <= N; i++) {
        sum[i] = num[i] + sum[i - 1];
    }

    int ans = num[1]; //ans保存最大子序列和,初始化为num[1]能保证最终结果正确
    //i和j分别是枚举的子序列的起点和终点
    for(int i = 1; i <= N; i++) {
        for(int j = i; j <= N; j++) {
            int s = sum[j] - sum[i - 1];
            if(s > ans) ans = s;
        }
    }
    printf("%d\n", ans);

    return 0;
}

分治O(n*log(n))

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int a[16177216];
ll solve(int l,int r){
	if(l==r) return a[r];
	int m=l+r>>1;
	ll lans=solve(l,m);
	ll rans=solve(m+1,r);
	ll sum=0;
	ll lmax=a[m],rmax=a[m+1];
	for(int i=m;i>=l;i--)
	{
		sum+=a[i];
		if(sum>lmax) lmax=sum;
	}
	sum=0;
	for(int i=m+1;i<=r;i++){
		sum+=a[i];
		if(sum>rmax) rmax=sum;
	}
	ll ans=lmax+rmax;
	if(lans>ans) ans=lans;
	if(rans>ans) ans=rans;
	return ans;
} 
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int n;
	while(cin>>n)
	{
		for(int i=1;i<=n;i++) cin>>a[i];
		cout<<solve(1,n)<<endl;
	}
	return 0;
}

DP O(n)

#include<bits/stdc++.h>
using namespace std;
int a[14839487];
int main(){
	int n,i;
	while(cin>>n){
		a[0]=0;
		for(i=1;i<=n;i++)
		cin>>a[i];
		int ans=a[1];
		for(i=1;i<=n;i++)
		{
			if(a[i-1]>0) a[i]+=a[i-1];
			if(a[i]>ans) ans=a[i];
		}
		cout<<ans<<endl;
	}
	return 0;
}

前缀和再优化 O(n)

#include<bits/stdc++.h>
using namespace std;
int a[14839487];
int main(){
	int n,i;
	while(cin>>n){
		a[0]=0;
		for(i=1;i<=n;i++)
		cin>>a[i];
		int ans=a[1];
		int lmin=0;
		for(i=1;i<=n;i++)
		{
			a[i]+=a[i-1];
			if(a[i]-lmin>ans)
			ans=a[i]-lmin;
			if(a[i]<lmin) lmin=a[i];
		}
		cout<<ans<<endl;
	}
	return 0;
}
posted @ 2018-08-15 15:24  ChunhaoMo  阅读(668)  评论(0)    收藏  举报