递归(上)
前言
在前几篇文章中我不断引用更改了国际象棋发明人被国王赏麦子的故事,这篇文章我还需要再借一下这两个人。
舍罕王和宰相达依尔来到了现代,这次舍罕王聪明了,他对宰相说,“这次我不用麦子赏你了,我直接给你发钱。另外,我也不用棋盘了,我直接给你一大笔固定数额的钱。”
宰相思考了一下,回答道:“没问题,陛下,就按照您的意愿。不过,我有一个小小的要求。能否您先列出所有可能的组合,让我自己来选呢?假设有四种面额的钱币,1元、2元、5元和10元,而您一共给我10元,那您可以奖赏我1张10元,或者5张1元加上1张5元等等……”
那么,如果考虑每次奖赏的金额和先后顺序,最终会有多少种不同的奖赏方式呢?
如何在限定总和的条件下求加和?
我们再帮国王想一想,要如何解决这个问题。
这个问题和棋盘的问题不同,它并不是要求总数,而是在总数限定的情况下,求所有可能的加和方式。
之前我写过的迭代法就是解决重复性操作的问题的,那我们先来看一看如何用迭代法解决。
迭代法
设 k 为每一次选择的次数,k = 1, 2, 3, 4, … n 。
当 k = 1时,即第一次选择,那么1元、2元、5元和10元这四种面值的都可以选择。
当 k = 2时,如果第一次选择的是 1 ,则这次有可能选1元、2元或者5元(如果选择 10,则超过了 10 元)。
按照这个思路,我们可以预见这个情况是十分复杂的。

这还只是奖金总额只有10元的情况。
所以虽然迭代法的思想是可行的,但是如果用循环来实现,必须要保存很多很多中间状态及其对应的变量。
因此,我们需要用另一个方法,递归法。
递归法
在函数的递归中,每次嵌套调用都会让函数体生成自己的局部变量,正好可以用来保存不同状态下的数值,为我们省去了大量中间变量的操作,极大地方便了设计和编程。
在我的数学归纳法讲解的文章末尾,我提到了数学归纳法和递归调用的一致性,递归编程体现了数学归纳法的思想。那么如果我们把这个思想泛化一下,递归就会用更多、更广阔的应用场景。
那么,如何把复杂的问题简单化?
首先,我们来看,如何将数学归纳法的思想泛化成更一般的情况?
数学归纳法考虑了两种情况:
- 初始状态。也就是 n = 1 的时候,命题是否成立;
- 其他状态。如果 n = k -1 的时候,命题成立。那么只要证明 n = k 的时候,命题也成立。其中 k 为大于 1 的自然数。
将上述两点顺序更换一下,再进行抽象化,就有了下面这样的递推关系:
- 假设 n = k -1 的时候,问题已解决(或者已经找到解)。那么只要求解 n = k 的时候,问题如何解决(或者解是多少)。
- 初始状态,就是 n = 1 的时候,问题如何解决(或者解是多少)。
这种思想就是将复杂的问题,每次都解决一点点,并将剩下的任务转化成为更简单的问题等待下次求解,如此反复,直到最简单的形式。
回到开头的问题,我们再将这种思想具体化。
- 假设 n = k - 1 的时候,我们已经知道如何去求

本文通过舍罕王与宰相达依尔的故事引入,探讨如何在限定总和条件下求加和问题。文章介绍了迭代法和递归法解决此问题,重点讲述了递归法的优越性,如何利用数学归纳法的思想进行递归编程,并指出递归在复杂问题分解中的重要性。最后,文章预告将深入讨论递归在分而治之策略中的应用。
最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



