1. 实践题目 —— 最大子段和
2. 问题描述
给定n个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。当所给的整数均为负数时,定义子段和为0。要求算法的时间复杂度为O(n)。
3. 算法描述
int MaxSum(int n, int *a)
{
int sum = 0, b = 0;
for(int i = 1; i <= n; i ++)
{
if(b > 0)
b += a[i];
else
b = a[i];
if(b > sum)
sum = b;
}
return sum;
}
4. 算法时间及空间复杂度分析
函数使用一个for循环以及3个条件判断语句寻找当前最大元素子段和,故时间复杂度为O(n);由于需要一个一位数组存放数组元素,故算法的空间复杂度为O(n)。
5. 心得体会
(1)使用动态规划思想解决问题时,首要问题是写出正确的递归式,这是算法的基本前提。在递归式正确的条件下,才能设计出合理的动态规划算法。
(2)对递归式的理解,或者说是对题目的理解一定要透彻到位,这样才能保证算法是求解题目的有效解决方案,也能让我们能够更加容易看懂书上的代码示例。
(3)使用递归解决动态规划问题时才需要使用备忘录,以便记录已经求解的子问题,减少大量重复运算,从而使算法的时间效率更高;而使用循环时,再建一个备忘录数组就是多此一举了。一开始没有分清备忘录的具体使用情况,从而有些混淆,后来经老师的提点,才知道自己“画蛇添足”了。
(4)在运用动态规划思想时,可以使用二维数组避免递归,但在填充二维数组时,要注意填表顺序,只有真正清楚了填表顺序才知道最终结果存放在哪里,以及编写相关代码。