USING INDUCTION TO DESIGN 使用归纳法设计算法 [2/14]

来源:互联网 发布:sql语句视频教程 编辑:程序博客网 时间:2024/04/28 06:44

接上文:http://blog.csdn.net/jj12345jj198999/article/details/6600734

 

这是一个非常强大和灵活的方法。我们将证明,在使用这种想法时很多问题变得很简单,这一点会让你惊讶不已。我们将采用其中的几种方法,并显示它们在设计算法时的强大力量。在我们讨论的归纳法的各种变形方法中,我们主要讨论巧妙的选择归纳序列,增强归纳假设,更强的归纳法以及最大的反例四种方法。

我们的处理方法有两种新奇之处。首先我们把看上去不同的算法设计技术归到同一个类别下,这将使得对一个新算法的查找更有条理性。其次,我们利用已知的数学证明技巧来设计算法,这一点很重要,因为它开启了利用在别的学科多年发展过程中形成的强大的技术进行算法设计的时代。

一般而言,在算法领域使用归纳法和数学证明技巧并不是第一次见到。归纳法在证明算法正确性上已经使用了很长时间,人们通过把对算法执行步骤的断言,证明它们在最初情况下成立和它们在特定操作步骤下保持不变结合起来,从而验证算法的正确性。这种方法最初由哥特斯和冯诺依曼提出的,后来由弗洛伊德和其他人对其进一步发展。Dijkstra和格里斯提出了一种和我们开发程序相似的方法,同时他们也给出了对其正确性的证明。尽管在此我们借鉴了他们的一些技术,但我们的重点却不同:我们关注于高层次的算法理念而不必下降到实际的程序层面。PRL和NuPRL(这里不会翻译,建议看http://www.cs.cornell.edu/info/projects/nuprl/book/node2.html)使用数学证明作为一个程序开发系统的基本构成。当然递归也被广泛用于算法设计之中(对于递归的详细讨论请看...)

我们的目标主要是用于教学,我们假设读者对数学归纳法和基本的数据结构已经很熟悉。对于任意一种证明技巧我们会对其类比进行一个简要的解释,然后给出一个或多个算法例子。对于给出的算法例子我们重点关注于如何使用这种方法。我们的目的不是在于对一个算法进行解释从而帮助一个程序员更容易地将其转换为程序,而是通过一种更容易理解的方式对其进行解释。这些算法通过一种创造性的过程加以解释而不是以一种成品的方式出现。我们教算法的目标不仅仅是向学生展示如何解决当前特定的问题,同时也是帮助他们解决未来新的问题。教学生如何把想法融入到算法设计中和教学生解决方案的实现细节同样重要。但前者通常要更难一些。我们相信我们的方法能够加强对这种思维过程的理解。

尽管归纳法建议通过递归加以实现,但也未必如此。(事实上我们称这种方法为归纳而不是递归,从而淡化递归实现的概念)在很多情况下,迭代也很容易,甚至尽管在算法设计中我们心里想的是使用归纳法(递归),但迭代却更有效率。

本文中提到的这些算法是经过筛选的,以便能更好的展现这种方法的魅力。我们选择的是一些简单的问题,在后续部分选择一些更复杂的例子。我们发现很多固定的算法在算法设计课上第一次教授时可以使用这种方法。(使用这种方法的算法导论书很快就要出来了)我们首先从三个简单的例子入手,(至少使用归纳法让他们看上去简单了)然后我们展示一些数学证明技巧以及它们在算法设计中类似的技巧,在每种情况下这种类比都在一个或多个例子中得到了阐明。

 

 

 

三个例子

 

计算多项式的值[Q1]
问题:给定一个实数序列an,an-1,...a1,a0和一个实数x,计算下面这个多项式的值
Pn(x)=an*x^n+an-1*x^(n-1)+...a1*x+a0
这个问题看上去并不像是一个使用归纳法求解直观例子,尽管如此,我们将证明使用归纳法能够直接带来很不错的解决方法。我们首先使用最简单几乎微不足道的方法求解,然后通过发现其中的变化,从而找到更好的解决方案。

这个问题涉及到n+2个数字。使用归纳法解决该问题的依据是对一个更小的问题进行求解。换句话说,我们尽量减小问题的规模,然后使用递归求解。(或者我们称其为归纳)第一步尝试是移除an,这将导致问题中计算的表达式变成:
Pn-1(x)=an-1*x^(n-1)+an-2*x^(n-2)+...+a1*x+a0
除了规模外这是一个同样的问题。因此我们可以使用下面的假设运用归纳法对其进行求解:
归纳假设:我们已经知道如何去计算一个多项式,该多项式在x处的输入项有an-1,...a1,a0(即我们知道如何计算Pn-1(x))

我们现在可以使用这假设运用归纳法来解决该问题。首先我们需要解决最基本的情况,也就是计算a0;这是很简单的。然后我们必须表明如何通过借助规模较小的问题的解决方案(这里是Pn-1(x)的值)来解决原有问题(即计算Pn(x))。在该例子中这是很直观的。我们仅仅需要计算x^n,乘以an然后加上Pn-1(x)即可。

在这一点上看上去使用归纳法很无聊因为它仅仅是复杂了一个简单的解决方案,上面提到的算法仅仅是按照多项式的数学方式对多项式从右到左进行计算而已。然而,我们很快就会看见这种方法的强大之处。

尽管这个算法是正确的,但其并不是高效的。它需要n+n-1+n-2+...+1=n(n+1)/2次乘法和n次加法计算。现在我们略微改变一下归纳法的使用方法,从而得到一个更好的解决方案。

 

原创粉丝点击