1.请以伪代码描述最大字段和的分治算法
先将元素分为a[0:(n-1)/2]与a[(n-1)/2+1:n-1]左右两个区间,那么最大字段和的存在有三种可能:
- 在左区间;
- 在右区间;
- 左端点在左区间,右端点在右区间;
继续递归划分直至只剩一个元素,寻找左区间、右区间、中间的最大字段和;
其中,中间字段可用如下代码实现:
for(int i=mid;i>=0;i--)//从中间往两边找
{
sum += a[i];
if(sum > max) max = sum;//如果相加后值大于之前的,更新max
}
sum = max;//左半边的最大字段找到了就是max
for(int i=mid+1;i<=right;i++)
{
sum += a[i];
if(sum > max) max = sum;
}//此时,max表示端点分别在左右区间的最大字段
而对左右两区间,不断调用函数即可;
调用过程图示:
主算法:
int maxmerge(int a[], int left, int right)
{
int mid = (left+right)/2;
int s1,s2,sum=0,max=-10000;
if(left == right) return a[left];
s1 = maxmerge(a,left,mid);
s2 = maxmerge(a,mid+1,right);
for(int i=mid;i>=0;i--)
{
sum += a[i];
if(sum > max) max = sum;
}
sum = max;
for(int i=mid+1;i<=right;i++)
{
sum += a[i];
if(sum > max) max = sum;
}
if(max<s1) max = s1;
else if(max<s2) max = s2;
return max;
}
- 分析该算法的时间复杂度
分解子问题:O(1)
求解子问题:2T(n/2)
合并子问题:O(n)
故时间复杂度为T(n)=2T(n/2)+O(n)=nlogn
3.结合本章的学习,你对分治法的体会和思考
首先,分治法的算法思想主要分为三个步骤:
- 将一个问题分解为多个相同类型的子问题;
- 求解这些子问题;
- 将所有子问题合并;
在不断划分求解的过程中,我们往往需要用到递归方法,直到达到递归结束条件,这个问题也就被分解完成,之后开始不断返回。
其次,分治法的应用场景十分广泛,从汉诺塔、各种二分拓展算法、归并排序、快速排序、线性时间问题(实际上还是快速排序的应用)、求逆序对、求最大字段和等均应用到分治法的思想,这种将大问题分解为小问题求解再合并的算法十分重要,不论是在算法、学习还是生活中都应该是我们拥有并掌握的基本思想。
最后,分治法与递归式,分治法的时间复杂度为:
T(n)=aT(n/b)+f(n) (n>1)
其中,a表示子问题的个数,n/b表示子问题的规模,则aT(n/b)表示求解子问题的时间,f(n)为分解与合并的时间,在求解时间复杂度时有: