最大子序列求和问题
最大子序列求和问题
问题描述
给定整数,,…, (可能有负数),求的最大值(为方便起见,如果所有整数均为负数,则最大子序列和为0)。
求解
算法1:
int max_sub_sum(const int A[], int N)
{
int sum, maxsum,i,j,k;
maxsum = 0;
for(i = 0; i<N; i++){
for(j = i; j<N; j++){
//求A[i]~A[j]的和
sum = 0;
for(k = i; k<j; k++){
sum += A[k];
}
if(sum > maxsum)
maxsum = sum;
}
}
return maxsum;
}
算法1的时间复杂度为
算法2:
int max_sub_sum2(const int A[], int N)
{
int sum, maxsum, i, j;
maxsum = 0;
for(i = 0; i<N; i++){
sum = 0;
for(j = i; j<N; j++){
sum += A[j];
if(sum > maxsum){
maxsum = sum;
}
}
}
return maxsum;
}
算法2的复杂度为,与算法1相比,算法2减少了一个内层循环
算法3
int maxsubsum(const int A[], int left, int right)
{
//采用分治法求解
if(left > right){
printf("error: left>right!\n");
return -1;
} else if(left == right) {
if(A[left]>=0) {
return A[left];
} else {
return 0;
}
} else {
int maxleftsum, maxrightsum, maxleftborder, maxrightborder, maxcrosssum, tmpsum;
int center, i;
center = (left+right)/2;
maxleftsum = maxsubsum(A, left, center);
maxrightsum = maxsubsum(A, center+1, right);
tmpsum = maxleftborder = 0;
for(i = center; i>=left; i--){
tmpsum += A[i];
if(tmpsum > maxleftborder) {
maxleftborder = tmpsum;
}
}
tmpsum = maxrightborder = 0;
for(i = center+1; i<=right; i++) {
tmpsum += A[i];
if(tmpsum > maxrightborder) {
maxrightborder = tmpsum;
}
}
maxcrosssum = maxleftborder+maxrightborder;
if(maxcrosssum >= maxleftsum && maxcrosssum >= maxrightsum)
return maxcrosssum;
if(maxleftsum >= maxcrosssum && maxleftsum >= maxrightsum)
return maxleftsum;
if(maxrightsum >= maxcrosssum && maxrightsum >= maxleftsum)
return maxrightsum;
}
}
int max_sub_sum3(const int A[], int N)
{
return maxsubsum(A, 0, N-1);
}
算法3用了分治法来求解,以序列的中间为分界线,最大子序列要么再左边一半,要么再右边一半,要么穿过中间,只要分别求左边一半最大子序列、右边一半最大子序列和穿过中间爱的最大子序列,最后从它们之间选出最大的即是整个序列的最大子序列,该分治算法的时间复杂度为
算法4
int max_sub_sum4(const int A[], int N)
{
int sum, maxsum, i;
sum = maxsum = 0;
for(i = 0;i<N; i++){
sum += A[i];
if(sum > maxsum) {
maxsum = sum;
} else if (sum < 0) {
sum = 0;
}
}
return maxsum;
}
算法4的时间复杂度为,该算法只要读一遍输入序列就可以算出最大子序列和
实验
#include <stdio.h>
#include <stdlib.h>
int max_sub_sum(const int A[], int N)
{
int sum, maxsum,i,j,k;
maxsum = 0;
for(i = 0; i<N; i++){
for(j = i; j<N; j++){
//求A[i]~A[j]的和
sum = 0;
for(k = i; k<j; k++){
sum += A[k];
}
if(sum > maxsum)
maxsum = sum;
}
}
return maxsum;
}
int max_sub_sum2(const int A[], int N)
{
int sum, maxsum, i, j;
maxsum = 0;
for(i = 0; i<N; i++){
sum = 0;
for(j = i; j<N; j++){
sum += A[j];
if(sum > maxsum){
maxsum = sum;
}
}
}
return maxsum;
}
int maxsubsum(const int A[], int left, int right)
{
//采用分治法求解
if(left > right){
printf("error: left>right!\n");
return -1;
} else if(left == right) {
if(A[left]>=0) {
return A[left];
} else {
return 0;
}
} else {
int maxleftsum, maxrightsum, maxleftborder, maxrightborder, maxcrosssum, tmpsum;
int center, i;
center = (left+right)/2;
maxleftsum = maxsubsum(A, left, center);
maxrightsum = maxsubsum(A, center+1, right);
tmpsum = maxleftborder = 0;
for(i = center; i>=left; i--){
tmpsum += A[i];
if(tmpsum > maxleftborder) {
maxleftborder = tmpsum;
}
}
tmpsum = maxrightborder = 0;
for(i = center+1; i<=right; i++) {
tmpsum += A[i];
if(tmpsum > maxrightborder) {
maxrightborder = tmpsum;
}
}
maxcrosssum = maxleftborder+maxrightborder;
if(maxcrosssum >= maxleftsum && maxcrosssum >= maxrightsum)
return maxcrosssum;
if(maxleftsum >= maxcrosssum && maxleftsum >= maxrightsum)
return maxleftsum;
if(maxrightsum >= maxcrosssum && maxrightsum >= maxleftsum)
return maxrightsum;
}
}
int max_sub_sum3(const int A[], int N)
{
return maxsubsum(A, 0, N-1);
}
int max_sub_sum4(const int A[], int N)
{
int sum, maxsum, i;
sum = maxsum = 0;
for(i = 0;i<N; i++){
sum += A[i];
if(sum > maxsum) {
maxsum = sum;
} else if (sum < 0) {
sum = 0;
}
}
return maxsum;
}
int main()
{
int A[]={-2, 11, -4, 13, -5, -2};
printf("max_sub_sum = %d\n", max_sub_sum(A, sizeof(A)/sizeof(int)));
printf("max_sub_sum = %d\n", max_sub_sum2(A, sizeof(A)/sizeof(int)));
printf("max_sub_sum = %d\n", max_sub_sum3(A, sizeof(A)/sizeof(int)));
printf("max_sub_sum = %d\n", max_sub_sum4(A, sizeof(A)/sizeof(int)));
return 0;
}