最简单和常见的数学归纳法是证明当n等于任意一个自然数时某命题成立。
证明分下面两步:
- 证明当n = 1时命题成立。
- 证明如果在n = m时命题成立,那么可以推导出在n = m+1时命题也成立。(m代表任意自然数)
这种方法的原理在于:首先证明在某个起点值时命题成立,然后证明从一个值到下一个值的过程有效。当这两点都已经证明,那么任意值都可以通过反复使用这个方法推导出来。把这个方法想成多米诺效应也许更容易理解一些。例如:你有一列很长的直立着的多米诺骨牌,如果你可以:
- 证明第一张骨牌会倒。
- 证明只要任意一张骨牌倒了,那么与其相邻的下一张骨牌也会倒。
那么便可以下结论:所有的骨牌都会倒下。
例如:等差数列求和公式:
1 + 2 + 3 + ··· + n = n (n+1) / 2
根据数学归纳法,这个问题应该这样证明:
- 当n = 1时,1 = 1 * 2 / 2成立;
- 假设n = n - 1时,1 + 2 + 3 + ··· + (n - 1) = (n - 1) n / 2成立,那么
原式左 = 1 + 2 + 3 + ··· + (n - 1) + n
= (n - 1) n / 2 + n
= n (n+1) / 2
= 原式右- 得证。
为什么要说这个呢?
其实在程序设计中,递归就用到了这个思想。
如果将上例运用递归用编程语言写出来如下:
public int sum(int n){
if(n < 1){
return -1;
}
if(n == 1){
return 1;
}
//假设n - 1成立,这是一般的情况。
//在代码书写中,先将一般的情况写出来构建出递归的框架,然后再去排除特殊的情况,以便完成递归。
return sum(n - 1) + n;
}
可以发现,这段代码将数学归纳法的思想恰当的体现了出来。
最后我们总结一下递归代码的书写方法:
递归书写方法:
- 严格定义递归函数作用,包括参数,返回值,side-effect
- 先一般,后特殊
- 每次递归必须缩小问题规模
- 每次问题缩小规模程度必须为1