最大子序列求和问题

最大子序列求和问题

问题描述

给定整数A1A2,…, AN(可能有负数),求k=ijAk的最大值(为方便起见,如果所有整数均为负数,则最大子序列和为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的时间复杂度为O(N3)

算法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的复杂度为O(N3),与算法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用了分治法来求解,以序列的中间为分界线,最大子序列要么再左边一半,要么再右边一半,要么穿过中间,只要分别求左边一半最大子序列、右边一半最大子序列和穿过中间爱的最大子序列,最后从它们之间选出最大的即是整个序列的最大子序列,该分治算法的时间复杂度为O(NlogN)

算法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的时间复杂度为O(N),该算法只要读一遍输入序列就可以算出最大子序列和

实验

#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;
}
posted @   main_c  阅读(347)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示