递归的思想

本文深入探讨了递归的概念,包括递归的两个关键要素:终止条件和逐步趋近。通过五个具体的递归编程实例,如阶乘、求和、顺序打印数字位、数字和及斐波那契数列,阐述了递归的使用方法。同时,对比了递归与迭代法在实现斐波那契数列时的效率差异,强调了递归思想的重要性,指出不论语言差异,解决问题的核心在于算法和逻辑。
摘要由CSDN通过智能技术生成

一、递归的思想

1. 递归分别表示递和归的两个动作,“ 函数递,函数归 ”。也就是说递归的本质是自己调用自己。

2. 函数递归要有两个必要的条件:
(1) 递归需要设置一个终止条件,以此来结束无限调用。
(2) 每一次的递归要无限趋近于这个条件。

如果不满足上面的这两个条件,函数递归就会无限地递归下去,直至栈溢出。栈溢出即表示栈区的内存被占满了。

如下图所示,当我们使用一个函数时,函数内的创建的局部变量都是放在栈区内存中存储的,如果无限递归下去不停止,就会导致栈区的内存超额。比如下面的 f 变量。

0

二、一些递归的题目

1. 递归求阶乘

程序清单1:

public class Test1 {
    public static void main(String[] args) {
        int n = 3;
        System.out.println(fac(n));
    }
    public static int fac(int n){
        if(n == 1){
            return 1;
        }else{
            return n * fac(n- 1);
        }
    }
}
//3*2*1 = 6

思想:
红色线条为递,绿色线条为归。
分析代码

2. 递归求和

程序清单2:

public class Test2 {
    public static void main(String[] args) {
        int n = 10;
        System.out.println(fac(n));
    }
    public static int fac(int n){
        if(n==1){
            return 1;
        }else{
            return n + fac(n- 1);
        }
    }
}
//10+9+8+...+2+1 = 55

3. 递归顺序打印一个给定数字中各个位数

程序清单3:

public class Test3 {
    public static void main(String[] args) {
        int n = 1357;
        fac(n);
    }
    public static void fac(int n){
        if(n/10 == 0) {
            System.out.print(n % 10+ " ");
        }else{
            fac(n / 10);
            System.out.print(n % 10+ " ");
        }
    }
}
//输出 1 3 5 7

分析:
(1) 上面代码通过 n / 10 和 n % 10 来进行转换位数,这里不再赘述
(2) 这里递归的终止条件是 n / 10 == 0,也就是说,碰到给定数字的个位数的时候,就 “ 归 ”

4. 递归输出一个数中各个数字相加之和

程序清单4:

public class Test4 {
    public static void main(String[] args) {
        int n = 1357;
        System.out.println(fac(n));
    }
    public static int fac(int n){
        if(n/10 == 0) {
            return ( n % 10 );
        }else{
            return fac(n/10) + n % 10;
        }
    }
}
// 1+3+5+7 = 16

5. 斐波那契数列的实现

0 1 1 2 3 5 8 13 21 34 55 89…
斐波那契数列的特点:
(1) F(0) = 0,F(1) = 1,F(2) = 1
(2) 当 n >= 2,F(n) = F(n - 1) + F(n - 2)

特点1就是终止条件,特点2就是实现规律的公式

程序清单5(递归法):

public class Test5 {
    public static void main(String[] args) {
        int n = 10;
        for (int i = 0; i <= n; i++) {
            System.out.println(fib(i));
        }
    }
    public static int fib(int n){
        if(n == 0){
            return 0;
        }
        if(n==1 || n==2){
            return 1;
        }else{
            return fib(n-1)+ fib(n-2);
    }
    }
}
//输出 0 1 1 2 3 5 8 13 21 34 55

程序清单5(迭代法):

public class Test5 {
    public static void main(String[] args) {
        int n = 10;
        fib(n);
    }
    public static void fib(int n){
        int a = 0;
        int b = 1;
        for (int i = 0; i <= n; i++) {
            if(i==0 || i==1){
                System.out.println(i);
            }
            else{
                int c = a + b;
                a = b;
                b = c;
                System.out.println(c);
            }
        }
    }
}
//输出 0 1 1 2 3 5 8 13 21 34 55

分析思路:

分析

总结

  1. 本人最近从 C 转到 Java,将递归又重新学了一遍,好处一在于巩固了算法,好处二在于熟悉新的代码风格,并增加了印象。其实不论是 C 还是 Java,实现的算法和逻辑都是相同的,只是语言不同,风格不同。
  2. 现在慢慢感受到了,语言只是工具,不论什么语言都是来解决问题的,语言不同只是语法层面上的不同,最重要还是要有解决问题的思想。
  3. 关于一些代码的细节部分没有赘述,比如函数内在的一些逻辑,比如递归求斐波那契数列为什么没有迭代法求出来更加高效。因为本篇博客旨在阐明递归的思想,读者可以从我给出的例子自我体会,只需要掌握每个问题的规律即可,没有必要深挖下去。
  4. 下一篇博客十七会分享使用递归来解决青蛙跳台阶和汉诺塔的问题。

结尾
Over. 谢谢观看哟~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十七ing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值