意想不到算法这一章的开篇就谈数学归纳法,呵呵,可见还是比较重要的。思路分两步走:(1)证明P1正确;(2)在P1、P2……Pn都正确的条件下,证明P(n+1)正确。这里特别说明要与科学上的归纳推理法区分开来,归纳推理法仅仅是基于现有情况的推测,并不一定正确,也没有被证明,而数学归纳法得到的是结论性的证明过程。
书中举了一个简单的数学例子。若要证明数学公式1+3+……+(2n-1)=n^2,(1)证明P1正确,明显1=1^2,成立;(2)由于Pn正确,即1+3+……+(2n-1)=n^2,对于P(n+1),1+3+……+(2n-1)+(2n+1)=n^2+2*n+1=(n+1)^2,成立。因此公式得证。
不过,在这书里讨论数学归纳法,并不仅仅为了证明数学公式,还为了证明算法实现程序的过程。这个感觉有点奇妙,思路是差不多的,证明也是分两步,首先证明程序执行第一步后得到的结果是正确的,然后证明,假设现在执行第n步后得到了正确的结果,根据这个结果执行第n+1步后得到的结果依然是正确的。有些算法(如迭代)是要经过多次循环才能得出最终结果,只要证明了这循环里面每一步得到的结果都正确,就可以证明整个算法的可行性。
然后书里举了一个于我而言比较难的例子,是关于扩展欧几里得定理算法实现的证明。扩展欧几里得算法不仅可以计算两个整数(a、b)的最大公约数,还可以计算a模b与b模a的乘法逆元,简单说若存在最大公约数d,则必存在ax+by=d,算法就是把d、x、y算出来。书中的实现过程分为四步:
E1.x0=y=1;x=y0=0;c=a;d=b;a>0;b>0;
E2.q=c/d;r=c%d;
E3.若r为0,则算法结束,a*x+b*y=d就是所求;若r不为0继续往下执行;
E4.c=d;d=r;t=x0;x0=x;x=t-q*x;t=y0;y0=y;y=t-q*y;返回第二步
刚看到这个实现过程时都傻眼了,完全不明白原理是什么。书里的证明过程是这样的:
执行E1后的结论:x*a+y*b=d;x0*a+y0*b=c;d>0;gcd(c,d)=gcd(a,b);
由上推出E2结论:x*a+y*b=d;x0*a+y0*b=c=q*d+r;0<=r<d;gcd(c,d)=gcd(a,b);
由上推出E3结论:若r=0:x*a+y*b=d=gcd(a,b);若r!=0:x*a+y*b=d;x0*a+y0*b=c=q*d+r;0<r<d;gcd(c,d)=gcd(a,b);
由上E4结论:x*a+y*b=d;x0*a+y0*b=c;d>0;gcd(c,d)=gcd(a,b);
接着继续循环执行E2,依然可以推出之前的结论,因为条件没有变,最后当执行E3跳出循环时就能得到正确的结果。这个证明过程关键是需要知道推出E2结论的条件,即x*a+y*b=d;x0*a+y0*b=c;接着下面的结论很自然地就出来了。但是这个条件我到现在还不明白是怎么发现的,书里也没有详细解释,只是说经过“a little study”。实际上,很多程序就是自己创造了一些条件,只要少数关键性的条件被发现了,后面的结论都很容易推出来。