一、实践题目
7-2 最大子段和 (40 分)
给定n个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。当所给的整数均为负数时,定义子段和为0。
要求算法的时间复杂度为O(n)。
输入格式:
输入有两行:
第一行是n值(1<=n<=10000);
第二行是n个整数。
输出格式:
输出最大子段和。
输入样例:
在这里给出一组输入。例如:
6
-2 11 -4 13 -5 -2
输出样例:
在这里给出相应的输出。例如:
20
二、问题描述
给出一段序列,求其中一段连续序列的最大值。
三、算法描述
递推方程式:dp[i] += dp[i-1];
易知当一段序列和为负数的时候必定不会是最大值。
所以当循环 dp[i] += dp[i-1] 时,dp[i] < 0 就把 dp[i] 置为 0。
在循环过程中,用一个 ans = ans>dp[i] ? ans:dp[i]; 记录最大值即可。
为了减少时间、空间复杂度,根据本题思路,在输入时即可直接记录。
故只开了 num 用于输入,dp = 0 用于记录当前连续的和,ans = 0 记录最大值。
具体代码:
#include
using namespacestd;intn;int num, dp = 0, ans = 0;intmain(){
scanf("%d", &n);while(n--){
scanf("%d", &num);
dp+=num;if(dp<0){
dp= 0;
}else{
ans= ans>dp ?ans:dp;
}
}
printf("%d", ans);return 0;
}
四、算法时间及空间复杂度分析(要有分析过程)
时间复杂度:1 + n * ( 1 + 1 + 1 * ( 1 + 1 ) ) + 1 = 1 + n + 1 = O(N)。
输入n : 1
{
// n 轮操作
输入num : 1
dp累加求和 : 1
判断dp是否小于0 : 1
{
小于0
{
dp置为0 : 1
}
大于等于0
{
判断ans是否大于dp : 1
ans赋值 : 1
}
}
}
输出ans : 1
空间复杂度:1 + 1 + 1 + 1 = O(1)。
n : 1
num : 1
dp = 0 : 1
ans = 0 : 1
五、心得体会(对本次实践收获及疑惑进行总结)
跟队友交流了一下,发现队友 7 - 1 的思路跟我不一样,我是自顶向下把最后一行的所有格子的最大值求出来,再循环求最大。队友的是自底向上直接求出最大值。
两个都不会 7 - 3 编辑距离,都研究了一会,上网学习了一回。收获就是思想碰撞,单题多解。