题目如下:
给定K个整数组成的序列{ N1 , N2 , …, NK},“连续子列”被定义为{ Ni, Ni+1, …, Nj},其中 1≤i≤j≤K。“最大子列和”则被定义为所有连续子列元素的和中最大者。例如给定序列{ -2, 11, -4, 13, -5, -2 },其连续子列{ 11, -4, 13 }有最大的和20。现要求你编写程序,计算给定整数序列的最大子列和。
本题旨在测试各种不同的算法在各种数据情况下的表现。各组测试数据特点如下:
数据1:与样例等价,测试基本正确性;
数据2:102个随机整数;
数据3:103个随机整数;
数据4:104个随机整数;
数据5:105个随机整数;
输入格式:
输入第1行给出正整数K (≤100000);第2行给出K个整数,其间以空格分隔。
输出格式:
在一行中输出最大子列和。如果序列中所有整数皆为负数,则输出0。
输入样例:
6
-2 11 -4 13 -5 -2
输出样例:
20
#include <stdio.h>
#define MaxN 100000
//在visual stdio 2019下需要下面这句话,粘贴到拼题A时需注释掉它
//#pragma warning( disable : 4996)
//a为传入数组名,K为数组长度
//1方法为暴力解法(对应视频中的解法1和2)
int MaxSeqSum1(int a[],int K);
//2方法为分而治之法
int Max3(int a, int b, int c);
int MaxSeqSum2(int a[], int K);
int DivideAndConquer(int a[], int left, int right);
//3方法为在线处理法
int MaxSeqSum3(int a[], int K);
int main()
{
int t;
int N;
scanf("%d", &N);
int test[MaxN];
for (t = 0; t <= N - 1; t++) {
scanf("%d", &test[t]);
}
//需要改变方法时将这的3改为1或2就行
printf("%d",MaxSeqSum3(test, N));
return 0;
}
//1方法为暴力解法
int MaxSeqSum1(int a[], int K){
int MaxSum = 0;
for (int j = 0; j <= K-1; j++) {
int ThisSum = 0;
for (int k = j; k <= K-1; k++) {
ThisSum = ThisSum + a[k];
if (ThisSum > MaxSum) {
MaxSum = ThisSum;
}
}
}
return MaxSum;
}
//2方法为分而治之法
int MaxSeqSum2(int a[], int K) {
return DivideAndConquer(a, 0, K-1);
}
int Max3(int a, int b, int c) {
int max;
if (a > b)
max = a;
else
max = b;
if (max > c)
max = max;
else
max = c;
return(max);
}
int k = 0;
int DivideAndConquer(int a[], int left, int right) {
int MaxLeftSum;
int MaxRightSum;
int MaxCenterSum;
int LeftBorderSum = 0;
int RightBorderSum = 0;
int MaxLeftBorderSum = 0;
int MaxRightBorderSum= 0;
int center = (left + right) / 2;
//递归的终止条件
if (left == right) {
if (a[left] >= 0)
return a[left];
else
return 0;
}
//分:递归求左右的最大子列和
MaxLeftSum = DivideAndConquer(a, left, center);
MaxRightSum = DivideAndConquer(a, center + 1, right);
//求跨越边界的最大子列和
for (int i = 0; i <= center - left; i++) {
LeftBorderSum = a[center - i] + LeftBorderSum;
if (LeftBorderSum > MaxLeftBorderSum)
MaxLeftBorderSum = LeftBorderSum;
}
for (int j = 1; j <= right - center; j++) {
RightBorderSum = a[center + j] + RightBorderSum;
if (RightBorderSum > MaxRightBorderSum)
MaxRightBorderSum = RightBorderSum;
}
MaxCenterSum = MaxLeftBorderSum + MaxRightBorderSum;
k = k + 1;
//printf("Left:%d Center:%d Right:%d 第%d次返回结果:%d\n", left, center, right, k, Max3(MaxCenterSum, MaxLeftSum, MaxRightSum));
return Max3(MaxCenterSum, MaxLeftSum, MaxRightSum);
}
//3方法为在线处理法
int MaxSeqSum3(int a[], int K) {
int ThisSum = 0;
int MaxSum = 0;
for (int i = 0; i <= K - 1; i++) {
ThisSum = ThisSum + a[i];
if (ThisSum > MaxSum)
MaxSum = ThisSum;
else if (ThisSum < 0)
ThisSum = 0;
}
return MaxSum;
}
提交结果:
需要注意的是在自己编函数时一定要注意要用标准的输入输出,否则不会显示答案正确(这部分在首页的课程介绍里有讲到)