赞
踩
目录
聊递归之前先看一下什么叫递归。
递归,就是在运行的过程中调用自己。
构成递归需具备的条件:
1. 子问题须与原始问题为同样的事,且更为简单;
2. 不能无限制地调用本身,须有个出口,化简为非递归状况处理。
我们用2个故事来阐述一下什么叫递归。
1,从前有座山,山里有座庙,庙里有个老和尚,正在给小和尚讲故事呢!故事是什么呢?“从前有座山,山里有座庙,庙里有个老和尚,正在给小和尚讲故事呢!故事是什么呢?‘从前有座山,山里有座庙,庙里有个老和尚,正在给小和尚讲故事呢!故事是什么呢?……’”
2,大雄在房里,用时光电视看着从前的情况。电视画面中的那个时候,他正在房里,用时光电视,看着从前的情况。电视画面中的电视画面的那个时候,他正在房里,用时光电视,看着从前的情况……
对于递归,这个函数的功能是什么,他要完成什么样的一件事,而这个,是完全由你自己来定义的。也就是说,我们先不管函数里面的代码什么,而是要先明白,你这个函数是要用来干什么。
例如,我定义了一个函数
- // 算 n 的阶乘(假设n不为0)
- int f(int n){
-
- }
这个函数的功能是算 n 的阶乘。好了,我们已经定义了一个函数,并且定义了它的功能是什么,接下来我们看第二要素。
所谓递归,就是会在函数内部代码中,调用这个函数本身,所以,我们必须要找出递归的结束条件,不然的话,会一直调用自己,进入无底洞。也就是说,我们需要找出当参数为啥时,递归结束,之后直接把结果返回,请注意,这个时候我们必须能根据这个参数的值,能够直接知道函数的结果是什么。
例如,上面那个例子,当 n = 1 时,那你应该能够直接知道 f(n) 是啥吧?此时,f(1) = 1。完善我们函数内部的代码,把第二要素加进代码里面,如下
- // 算 n 的阶乘(假设n不为0)
- int f(int n){
- if(n == 1){
- return 1;
- }
- }
有人可能会说,当 n = 2 时,那我们可以直接知道 f(n) 等于多少啊,那我可以把 n = 2 作为递归的结束条件吗?
当然可以,只要你觉得参数是什么时,你能够直接知道函数的结果,那么你就可以把这个参数作为结束的条件,所以下面这段代码也是可以的。
- // 算 n 的阶乘(假设n不为0)
- int f(int n){
- if(n <= 2){
- return n;
- }
- }
第三要素就是,我们要不断缩小参数的范围,缩小之后,我们可以通过一些辅助的变量或者操作,使原函数的结果不变。
例如,f(n) 这个范围比较大,我们可以让 f(n) = n * f(n-1)。这样,范围就由 n 变成了 n-1 了,范围变小了,并且为了原函数f(n) 不变,我们需要让 f(n-1) 乘以 n。
说白了,就是要找到原函数的一个等价关系式,f(n) 的等价关系式为 n * f(n-1),即
f(n) = n * f(n-1)。
- // 算 n 的阶乘(假设n不为0)
- int f(int n){
- if(n <= 2){
- return n;
- }
- // 把 f(n) 的等价操作写进去
- return f(n-1) * n;
- }
我们先来看一个最简单的递归调用-阶乘,代码如下
- <script>
- // ======================n的阶乘======================
- // n的阶乘:n!=n*(n-1)*...*3*2*1;
- // 1、公式:fn(n)=fn(n-1)*n;(也可写为:fn(n)=n*fn(n-1))
- // 2、终点:fn(1)=1;
-
- function fn(n) {
- if (n === 1) {
- return 1;
- } else {
- return fn(n - 1) * n;
- }
- }
- console.log(fn(5));
- // 打印上面函数执行之后的返回值。
-
- // 公式推导:2=2*1; ==> fn(2)=2*fn(1);
- // 3=3*2*1 ==> fn(3)=3*fn(2);
- // 4=4*3*2*1 ==> fn(4)=4*fn(3);
- // ...
- // n=n*(n-1)*...*3*2*1 ==> fn(n)=n*fn(n-1);
- // 总结:运用递归思想,找好公式和终点(最重要)。
- </script>
斐波那契数列的是这样一个数列:1、1、2、3、5、8、13、21、34....,即第一项 f(1) = 1,第二项 f(2) = 1.....,第 n 项目为 f(n) = f(n-1) + f(n-2)。求第 n 项的值是多少。
- <script>
- // ==================斐波那契数列==================
- // 斐波那契数列:1、1、2、3、5、8、13、21、34、55、89...
- // 同理:先找公式和终点。
- // ==>从第三位开始,前两位数之和得到自己。
- // 前提:设置n为位数。n表示第n位。
- // 1、公式:fn(n)=fn(n-1)+fn(n-2);
- // 2、终点:fn(1)=1;f(2)=1;
- // 前两位数没有规律,第三位开始规律;双终点。
-
- function fn(n) {
- if (n === 1 || n === 2) {
- return 1;
- } else {
- return fn(n - 1) + fn(n - 2);
- }
- }
- console.log(fn(7));
- </script>
- <script>
- // ==================电影院找座位(问前排)==================
- // 同理:先找公式和终点。
- // 1、公式:fn(n)=fn(n-1)+1;
- // 2、终点:fn(1)=1;(第一排前面没人了,知道自己是第一排)
- function fn(n) {
- if (n === 1) {
- return 1;
- } else {
- return fn(n - 1) + 1;
- }
- }
- console.log(fn(5));
- </script>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。