求解递归式的方法:
1. 带入法:猜想一个界,然后用数学归纳法证明这个界是正确的(看到这顿时感觉回到了中学笔推的时代);
2. 递归树法:将递归转换为一颗树,其节点表示不同层次的调用产生的代价,然后用边界和技术来求解递归式;
3. 主方法: 可求解如下公式递归式的界:T(n) = aT(n/b) + f(n),这里刻划了一个分治算法:生成a个子问题,每个问题的规模是原有规模的1/b,分解和合并花费的时间为f(n).
例子:求最大连续子数组之和.
解决方法:采用分治策略进行分解,最大连续子数组必然位于以下三个位置:中间位置的左边、中间位置的右边、横跨中间位置。分情况讨论之。 时间效率为O(n*log n)
代码如下:
int ClsAlgoriIntro::max_subarray_sum(const int A[],int Left,int Right,int &start,int &end,int &maxSum)
{
int MaxLeftSum,MaxRightSum; //左、右部分最大连续子序列值。对应情况【1】、【2】
int MaxLeftBorderSum,MaxRightBorderSum; //从中间分别到左右两侧的最大连续子序列值,对应case【3】。
int LeftBorderSum,RightBorderSum;
int Center,i;
if(Left == Right)
{
if(A[Left]>0)
return A[Left];
else
return 0;
}
Center=(Left+Right)/2;
MaxLeftSum=max_subarray_sum(A,Left,Center,start,end,maxSum);
MaxRightSum=max_subarray_sum(A,Center+1,Right,start,end,maxSum);
MaxLeftBorderSum=0;
LeftBorderSum=0;
for(i=Center;i>=Left;i--)
{
LeftBorderSum+=A[i];
if(LeftBorderSum>MaxLeftBorderSum)
{
MaxLeftBorderSum=LeftBorderSum;
start = i;
}
}
MaxRightBorderSum=0;
RightBorderSum=0;
for(i=Center+1;i<=Right;i++)
{
RightBorderSum+=A[i];
if(RightBorderSum>MaxRightBorderSum)
{
MaxRightBorderSum=RightBorderSum;
end = i;
}
}
int max1=MaxLeftSum>MaxRightSum?MaxLeftSum:MaxRightSum;
int max2=MaxLeftBorderSum+MaxRightBorderSum;
maxSum = max1>max2?max1:max2;
return maxSum;
}