1.暴力求解
#include <stdio.h>
int subset_direct(int *A,int n)
{
int sum_max = -99999;
for(int i=0;i<n;i++){
int sum = 0;
for(int j=i;j<n;j++){
sum = sum+A[j];
if(sum>sum_max){
sum_max = sum;
}
}
}
return sum_max;
}
int main()
{
int A[]={1,2,8,-3,-8,-2,6,10,5,-6};
printf("%d\n",subset_direct(A,10));
return 0;
}
2.分治策略
#include <stdio.h>
int max_num(int a,int b,int c)//返回3个数中的最大值
{
int max;
max = a;
if(max<b)
max = b;
if(max<c)
max = c;
return max;
}
int max_subset(int A[],int left,int right)
{
int mid,i;
int max_left,max_right;//左半部分和右半部分最大值
int max_left_border=0,max_right_border=0;//包括左边界和右边界的最大值
int sum_left_border=0,sum_right_border=0;//包括左边界和右边界的值
if(left==right){
return A[left];
}
mid = (left+right)/2;
max_left = max_subset(A,left,mid);
max_right = max_subset(A,mid+1,right);
for(i=mid;i>=left;i--){
sum_left_border += A[i];
if(sum_left_border>max_left_border){
max_left_border = sum_left_border;
}
}
for(i=mid+1;i<=right;i++){
sum_right_border += A[i];
if(sum_right_border>max_right_border){
max_right_border = sum_right_border;
}
}
return max_num(max_left,max_right,max_left_border+max_right_border);
}
int main()
{
int A[] = {1,2,8,-3,-8,-2,6,10,5,-6};
int max;
max = max_subset(A,0,9);
printf("%d ",max);
return 0;
}
3.线性求解
#include <stdio.h>
int linear_subset(int A[],int n)
{
int i;
int temp = 0;
int max_sum = 0;
for(i=0;i<n;i++){
temp +=A[i];
if(temp>max_sum){
max_sum = temp;
}
if(temp<0){
temp = 0;
}
}
return max_sum;
}
int main()
{
int A[] = {1,2,8,-3,-8,-2,6,10,5,-6};
int max;
max = linear_subset(A,10);
printf("%d ",max);
return 0;
}
关于线性求解,我自己也说不清楚,需要自己多琢磨。
如果a[1..j]已经得到了其最大子数组,那么a[1..j+1]最大子数组只能是两种情况
(1)a[1..j+1]的最大子数组就是a[1..j];
(2)a[1..j+1]的最大子数组是a[i..j+1],1<=i<=j;
那么,如何求得所谓的(2)中的a[i..j+1]呢?
首先需要承认这样的事实,如果一个数组a[p..r]求和得到负值,那么数组a[p..r+1]的最大子数组肯定不会是a[p..r+1],因为a[p..r]+a[r+1]