关于最大子序列和问题的解在书中一共看到了四种方法,前两种方法均是通过比较所有可能的子序列的和求解,而第三种采用递归方法算是有了较大的改进,而第四种更是nice。
下面是对每一种方法的实现
第一种时间复杂度是O(N^3):
/*
*Author:gyh
*Date:20141225
*/
#include<stdio.h>
#include<math.h>
void maxsubsequencesum(const int a[], int n);
int main(void){
int a[8] = { 4, -3, 5, -2, -1, 2, 6, -2};
maxsubsequencesum(a, 8);
return 0;
}
void maxsubsequencesum(const int a[], int n){
int thissum = 0;
for(int i = 0; i < n; i++){
for(int j = i; j < n; j++){
int sumnow = 0;
for(int k = i; k < j; k++){
sumnow += a[k];
}
if(thissum < sumnow){
thissum = sumnow;
}
}
}
printf(" %d\n", thissum);
}
第二种时间复杂度是O(n^2):
/*
*Author:gyh
*Date:20141225
*Version:2.0
*/
#include<stdio.h>
int main(void){
void maxsubsequencesum(const int a[], int n);
int a[] = { 4, -3, 5, 2, -1, -2, 6, -2};
maxsubsequencesum(a, 8);
return 0;
}
void maxsubsequencesum(const int a[], int n){
int thissum = 0;
for(int i = 0; i < n; i++){
int sumnow = 0;
for(int j = i; j < n; j++){
sumnow += a[j];
if(sumnow > thissum) thissum = sumnow ;
}
}
printf(" %d\n", thissum);
}
第三种时间复杂度是O(nlogn):
/*
*Author:gyh
*Date:20141225
*Version:3.0
*/
#include<stdio.h>
int maxsum(const int a[], int left, int right);
void maxsubsequencesum(const int a[], int n);
int main(void){
int a[] = { 4, -3, 5, -2, -1, 2, 6, -2};
maxsubsequencesum(a, 8);
return 0;
}
void maxsubsequencesum(const int a[], int n){
printf(" %d\n", maxsum(a, 0, n-1));
}
int maxsum(const int a[], int left, int right){
int leftbordersum, rightbordersum;
int maxleftsum, maxrightsum;
int maxleftbordersum, maxrightbordersum;
int center;
if(left == right){ //如果只含有一个数则返回
if(a[left] > 0){
return a[left];
}
else{
return 0;
}
}
center = (left + right)/2;
maxleftbordersum = 0;
maxrightbordersum = 0;
leftbordersum = 0;
rightbordersum = 0;
for(int i=center; i >= left; i--){ //计算左边界和的最大值
leftbordersum += a[i];
if (maxleftbordersum < leftbordersum){
maxleftbordersum = leftbordersum;
}
}
printf("maxleftbordersum = %d ", maxleftbordersum);
for(int i=center+1; i <= right; i++){ //计算右边界和的最大值
rightbordersum += a[i];
if(maxrightbordersum < rightbordersum){
maxrightbordersum = rightbordersum;
}
}
printf("maxrightbordersum = %d\n", maxrightbordersum);
maxleftsum = maxsum(a, left, center);
maxrightsum = maxsum(a, center + 1, right);
printf("maxleftsum = %d maxrightsum = %d\n", maxleftsum, maxrightsum);
if(maxleftbordersum + maxrightbordersum < maxleftsum){
/*如果左右边界的最大值之和大于左右最大子序列和则返回左右边界最大值和否则返回最大值*/
if(maxleftsum > maxrightsum) return maxleftsum;
else if(maxleftbordersum + maxrightbordersum < maxrightsum) return maxrightsum;
}else if(maxleftbordersum + maxrightbordersum < maxrightsum) return maxrightsum;
else return maxleftbordersum + maxrightbordersum;
}
第四种时间复杂度为O(n)
/*
*Author:gyh
*Date:20141225
*Version:4.0
*/
#include <stdio.h>
int main(void){
int a[] = { 4, -3, 5, -2, -1, 2, 6, -2};
int thissum, sumnow = 0;
thissum = 0;
for(int i = 0; i < 8; i++){
sumnow += a[i];
if(thissum < sumnow) thissum = sumnow;
else if(sumnow < 0) sumnow = 0;
}
printf(" %d\n", thissum);
return 0;
}