题目来源
浙大数据结构MOOC-PTA的课后题
题目内容
分析
这个程序在课程里讲过,一共有四种方法,其中两种是同一种方法,只是进行了优化,这道题没有什么好分析的,直接写就行了。
我的程序
-
暴力穷举:
#include <stdio.h> int main() { // 获取数据 int size; scanf("%d", &size); int num[size]; int max = 0, this = 0; for(int i = 0; i < size; i++) { scanf("%d", num + i); } // 穷举所有子列并找出最大和 for(int i = 0; i < size; i++) // 分别以每个项作为子列起点,然后计算这个起点所有子列和 { this = 0; // 每次计算完子列,都需要清空 for(int j = i; j < size; j++) // 计算当前所在起点的所有子列和 { this += num[j]; if(this > max)max = this; // 当出现了更大的子列和时,将其存入max } } printf("%d", max); // 打印出来 return 0; }
这种解法的时间复杂度为O(N2),虽然能用但是还差点意思。
-
分而治之:
#include <stdio.h> int getMaxSequenceSum(int* num, int size); int main() { int size; scanf("%d", &size); int num[size]; int max = 0; for(int i = 0; i < size; i++) { scanf("%d", num + i); } max = getMaxSequenceSum(num, size); printf("%d", max); return 0; } int getMaxSequenceSum(int* num, int size) // 分而治之,左右分并分别计算最大子列和,然后从中间向两边延申计算最大子列和,比较三者,最终得到最大子列和 { if(size == 1) { return num[0]>0?num[0]:0; // 不可再分时,最大子列和就是本身或0(小于0的情况) } int left = getMaxSequenceSum(num, size / 2); int right = getMaxSequenceSum(num + size / 2, size - size / 2); int mid_l = 0, mid_r = 0; int max = 0, this = 0; for(int i = 1; i <= size / 2; i++) { this += num[size / 2 - i]; if(mid_l < this)mid_l = this; } this = 0; for(int i = 0; i < size / 2; i++) { this += num[size / 2 + i]; if(mid_r < this)mid_r = this; } max = mid_l + mid_r > left?mid_l + mid_r:left; return max > right?max:right; }
这种解法的时间复杂度为O(NlogN),已经是一种非常优秀的解法了。
-
在线处理:
#include <stdio.h> int main() { // 获取数据 int size; scanf("%d", &size); int num[size]; int max = 0, this = 0; for(int i = 0; i < size; i++) { scanf("%d", num + i); this += num[i]; if(this > max)max = this; else if(this < 0)this = 0; } printf("%d", max); // 打印出来 return 0; }
在线处理的时间复杂度是O(N),时间复杂度是线性的算法,是该问题的最优解。
运行结果
下面的配图是我在MOOC中提交的图,里面代码没有优化,所以结果可能和预期有一点差别,不过整体大差没差。
1.暴力穷举
2.分而治之
3.在线处理