今天在看《C++语言描述(第3版)_Mark Allen Weiss》时,看到 第二章的四种求解最大子序列的方法,对于第四种解法,书上有言:“这是许多聪明算法的典型:运行时间是明显的,但正确性则不明显。对于。。。;然而即便如此许多仍然不信服。” 好吧,这句话激起了我的兴趣。
//最大子序列必然是序列中间的一部分:去掉序列的头部啊和尾部b,且知道,去掉的两部分必定小于0. 那么问题来了,中间这部分怎么找?
int maxSubSum4( const vector<int> & a )
{
int maxSum = 0;
int thisSum = 0;
for(int j = 0; j <a.size(); j++ )
{
thisSum += a[j] ;
if(thisSum > maxSum) //maxSum只记录最大和,thisSum忠实记录每一和,只有大于maxSum才会被记录
maxSum = thisSum;
else if( thisSum < 0 ) //将a置为0,则不影响最大的和
thisSum = 0;
}
}
算法的好处:只对数据进行一次扫描,一旦 a[i] 被读入并被处理,它就不需要被记忆,更棒的是:在任意时候算法都能对它已经读入的数据给出子序列问题的正确答案,具有这种特性的算法叫做 联机算法(on-line algorithm)
我对这种解法的解释:
我们不妨采取逆向理解:假设我们已经找到了一个数列的 最大 子序列 a[m]...........a[n] (n >m) , 在此序列的前缀或是后缀,如果有不为负(也不为零)的子序列存在,则最大子序列的和将会增加,则与我们已经找到最大子序列矛盾,同时这里也向世人证明一条定理:最大子序列的前缀或是后缀子序列都不为正!