最近面试好几次遇到同一个面试题:给定一个整数数组,数组里可能有正数、负数和零。数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。求所有子数组的和的最大值。
《算法导论》里用分治算法解决此类问题,使时间复杂度达到lgN,后来发现此题用动态规划求解更好一点。
动态规划的思想是用已知的结果决策之后的一层。此题中,假设数组为int items[7] = { 2,5,-3,5,7,-9,6 },我们用sub保存临时连续最大值,result代表结果,都先取第一个元素。
首先第一个成员2是起始元素,我们根据2决策5,因为2>0,所以sub=2+5;如果第一个元素<0,即sub<0,那么sub直接取5。第一次决策结束,所以结果包含两种情况{以第2个元素结束的sub,仅仅表示第二个元素的sub},其他不必考虑。
第二次决策-3,同理,如果sub>0,sub=sub+ -3;如果sub<0,则sub置为-3.
以此类推~
我们不必考虑考虑诸多复杂情况,因为每一层的决策都是由之前的结果得到,下面附上代码:
int dynamicProgram(int *array, int N)
{
//DP算法求解最大连续子数组和
int sub = array[0],result=array[0];
for (int i = 1; i < N; ++i) {
if (sub > 0) sub += array[i];
else sub = array[i];
if (sub > result) result = sub;
}
return result;
}
如果需要知道起始位置和末位置,只需要传入起始变量和末变量,在第一个if里更新末变量,else里更新起始变量。