1.1最大连续子数组
给定一个数组A[0,1,…,n-1],求A的连续子数组,使得该子数组的和最大。
例如:数组:1,-2,3,10,-4,7,2,-5
最大子数组:3,10,-4,7,2
1.1.1 暴力法
直接求解。时间复杂度o(n^3)。
(等我学会C++!)
#include <stdio.h>
#include <math.h>
int MaxSubArray(int a[],int n)
{
int max=a[0];
int crr;
for(int i=0;i<n;i++)
{
for(int j=i;j<n;j++)
{
crr=0;
for(int k=i;k<=j;k++)
{
crr+=a[k];
}
if(crr>max)
max=crr;
}
}
return max;
}
int main()
{
printf("请输入数组个数:\n");
int n;
scanf("%d",&n);
int a[n];
printf("请输入数组数据:\n");
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
int max;
max=MaxSubArray(a,n);
printf("最大子数组和为:%d\n",max);
}
1.1.2 分治法
将数组从中间分开,那么最大子数组要么完全在左半边数组,要么完全在右半边数组,要么跨立在分界点上。
完全在左右数组,递归解决。
跨立在分界点上:实际上是左数组的最大后缀和右数组的最大前缀的和。因此,从分布点向前扫,向后扫即可。
代码:
#include <stdio.h>
#include <math.h>
#define max(a,b) (a>b)?a:b
int max2(int a,int b,int c)
{
int big;
if(a >= b)
big = a;
else
big = b;
if(c> big)
big = c;
return big;
}
int MaxSub(int a[],int from,int to)
{
if(to==from)
return a[from];
int mid=(from+to)/2;
int m1=MaxSub(a,from,mid);
int m2=MaxSub(a,mid-1,to);
int i,left=a[mid],now=a[mid];
for(i=mid-1;i>=from;i--)
{
now+=a[i];
left=max(now,left);
}
int right=a[mid+1];
now=a[mid+1];
for(i=mid+2;i<=to;i++)
{
now+=a[i];
right=max(now,right);
}
int m3=left+right;
return max2(m1,m2,m3);
}
int main()
{
printf("请输入数组个数:\n");
int n;
scanf("%d",&n);
int a[n];
printf("请输入数组数据:\n");
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
int max;
max=MaxSub(a,0,n);
printf("最大子数组和为:%d\n",max);
}