都说看过了并不是你的,只有做过了才是你的。
第一次遇到这个题目是在算法基础课程的期末考试上,我当时这道题留了白;后来在《编程之美》里不小心又遇到了,只知道它使用了动态规划的思想,但没细看;第三次遇到是在实习面试的时候,没想到又留白了。事不过三,事过了“四”就不是事了,是绊脚石。所以我有写一点东西的必要,写过了才是自己的。
一看到最大值,心里就应该想到,最终程序里必定有这么一个过程:在一个序列里比较查找最大值。但是这个序列是什么呢?记得算法基础老师说过,动态规划其实不难,有了公式其实程序很容易实现,难就难在如何定义一些符号含义(往往在定义符号表示之后就豁然开朗了),然后把解决方案表示成公式。
好家伙,对于这道题,我们把f(i)定义为第 i 个数字结尾的子数组的最大和,如果我们已经知道了以每个数字结尾的子数组的最大和,那就需要在这些最大和中寻找一个最大值,这就是之前所说的必定会存在的操作。所以,现在问题就变为了如何求解以一个数字结尾的子数组的最大和。
以第1个数字结尾的子数组只有它本身,所以我们知道了以第1个数字结尾的子数组的最大和。以第2个数字结尾的子数组有2个,以第3个数字结尾的子数组有3个,对于以第3个数字结尾的子数组的最大和,要么是第3个数字加上以第2个数字结尾的子数组的最大和,要么是第3个数字(当以第2个数字结尾的子数组的最大和小于等于0时)。以此类推,得到如下公式:
计算所有f(i)并找出其中的最大值,两个步骤和二为一,可以得到O(n)的效果。
int max_sub_vector_sum(std::vector<int> const& values) {
int sn=0;
int max_sum=values.at(0);
for(vector<int>::const_iterator iter=values.begin();iter!=values.end();iter++)
{
if(sn<=0)
sn=*iter;
else
sn=sn+*iter;
if(sn>max_sum)
max_sum=sn;
}
return max_sum;
}