这道题在陈越姥姥的数据结构课中出现了,姥姥提出了四种解法。第一种是暴力的方法,即求出每个子序列和的大小,进行比较。第二种是在第一种的方法上稍加优化,减少累加次数。
第三种算法叫“分而治之”,把一个数组一分为二,一直分下去,直到左右两端各一个元素。此时求出左端子序列的最大值,求出右端子序列的最大值,再求出跨越左右两端子序列的最大值。三个最大值中最大的那一个,才是这个区间内子序列和的最大值,大于零将其返回,否则返回0。最终是分成单个元素的,同理返回即可。这里用到的递归的算法,是我自己写的,可能不够简洁,不过还是能够通过测试点的。其复杂度为O(NlogN)。
#include<iostream>
using namespace std;
int GetMax(int a, int b);
int Fun(int a, int b);
int K, array[100000];
int main(){
int maxSum = 0;
cin >> K;
for(int i = 0; K - i > 0; i++){
cin >> array[i];
}
maxSum = Fun(0, K - 1);
printf("%d", maxSum);
}
int Fun(int a, int b){
int max, tempA, tempB, tempC;
int left = 0, leftMax = 0, right = 0, rightMax = 0;
if(a != b){
tempA = Fun(a, (a + b) / 2);
tempB = Fun((a + b) / 2 + 1, b);
for(int i = (a + b) / 2; i >= a; i--){
left += array[i];
if(left > leftMax){
leftMax = left;
}
}
for(int i = (a + b) / 2 + 1; i <= b; i++){
right += array[i];
if(right > rightMax){
rightMax = right;
}
}
tempC = leftMax + rightMax;
max = GetMax(tempA, tempB);
max = GetMax(tempC, max);
}else{
max = array[a];
}
if(max > 0) return max;
else return 0;
}
int GetMax(int a, int b){
return a > b ? a : b;
}
第四种算法复杂度为O(N),姥姥将其称为“在线处理”。从第一个元素开始检查,如果thisSum > maxSum,则更新maxSum;如果thisSum < 0,则将thisSum置为0。即舍弃前面的序列。具体介绍请参考姥姥的课程视频!
#include<iostream>
using namespace std;
int main(){
int K, array[100000];
int thisSum = 0, maxSum = 0;
cin >> K;
for(int i = 0; K - i > 0; i++){
cin >> array[i];
}
for(int i = 0; i < K; i++){
thisSum += array[i];
if(thisSum > maxSum){
maxSum = thisSum;
}else if(thisSum < 0){
thisSum = 0;
}
}
printf("%d", maxSum);
}