如果一个问题能够分成若干子问题,这些子问题结构与原问题相同但参数更小从而更易解决,这种问题就可以考虑归纳的算法思想。最近学到两个利用归纳思想可巧妙地解决的问题,觉得记下来值得慢慢回味。
问题1 给定一串实数an, an-1,……, a1, a0和一个实数x,计算多项式Pn(x)= anxn+ an-1xn-1+……+ a1x+ a0的值。
[解法一] 依次循环地计算出多项式各项,然后相加起来。这是最简单也是最低效的解法。共有n+(n-1)+……+1=n(n+1)/2次乘法和n次加法。
[解法二]将多项式分成子问题Pn-1(x)=an-1xn-1+……+ a1x+ a0,这个子问题与原问题结构完全一样,只是项数是n-1,因此可以递归解决。
[归纳假设一]已知如何计算Pn-1(x)的值,求Pn(x)= anxn+ Pn-1(x)。在这种归纳假设下计算Pn(x)是很容易的,但是与解法一在复杂度上没有区别,甚至由于递归调用而更差。
可以注意到,在计算Pn(x)时需要计算x的n次方,而Pn-1(x)时已知道x的n-1次方,利用这个信息可以省去不少重复计算,因此有如下归纳假设。
[归纳假设二]已知如何计算Pn-1(x)和xn-1的值,求Pn(x)= anxn+ Pn-1(x)。此时计算anxn时只需要2次乘法,因此共需2n-1次乘法(n=1时只有一次)和n次加法,比假设一情况有了不少改善,这也是很多人能想到的。其实此算法还能进一步改进,逆向地思考如下
[归纳假设三]将问题分成这样的子问题,去掉常数a0及使剩下每项的x降低一次幂,亦即Pn-1’= anxn-1+……+ a2x+ a1,于是Pn=x Pn-1’+a0,这样于是只需要乘法和加法各n次,比归纳假设二又改进了不少。
问题2 从集合S={x1, x2,……, xn}中找出最大和第二大的元素。
[解法一]当然可以直接进行2n-3次比较即可求出,最简单也最低效。
[解法二]将S平均分成两个子集合S1和S2,若知道了S1的最大和第二大元素为p1,p2,S2的最大和第二大元素为q1,q2,则通过比较p1和q1即可知S的最大值,再通过一次比较可知第二大元素。这样的时间复杂度递归表达式为T(2n)=2T(n)+2,解之T(n)=3n/2-2,这比解法一改善了一些。还有更复杂的算法可以将复杂度降到n-1+log2n-1,实现更麻烦,不到关键时刻不能牛刀杀鸡,用时再学吧。