JavaSE -- 方法(下)--浅谈递归

本文通过浅谈递归概念,详细介绍了递归的三个关键要素:明确目的、设置终止条件和等价关系式。通过实例演示如何用递归求阶乘、打印数字每一位、求和及斐波那契数列。最后,探讨了递归在大数据和效率上的挑战,并介绍了迭代作为优化方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

上次在C语言阶段,笔者(笔者菜鸟起飞)就一直想写一篇关于递归的文章,来初步总结一下自己的思路,但是后面由于各种各样的事情耽搁后来想法就搁浅了,这次到JAVA可算给我逮着机会了!!!!

PS:可能知识比较浅,但是会尽力写好!!

一丶浅谈递归概念

首先,何为递归?

定义:一个方法在执行过程中调用自身, 就称为 “递归”

初步理解的话,可以用民间流传的口头文学的这样一个小故事来理解:

从前有座山,山里有座庙,庙里有个老和尚在给小和尚讲故事,讲的什么呢? 讲的是:从前有座山,山里有座庙,庙里有个老和尚在给小和尚讲故事…

这里的话,就可以理解为一种不太健全的递归,因为他在讲故事的过程中不断地重复自身这一点和递归很像,但是为什么说他不健全?因为他没有结束条件

在日常中,递归的思想也广为应用,比如数学解题方法上的“数学归纳法”,比如算法里面的"二分法查找"…

最后用一句大白话来总结递归:

大事化小,小事化了!

二丶递归的三要素

<1>明确目的 / 明确功能

故事总要有个开头,就比如《青玉案·元夕》,你不蓦然回首,你咋会知道她就在灯火阑珊处呢?所以我们在一开始就要有目的,如下题:

递归求 N 的阶乘!

我们的目的是求阶乘,所以:

//这里是求阶乘的!!!
public static int factor(int n) {

}

是的,先定义一个漂亮的方法名,然后开始我们的征程!

<2>明确终止条件

递归方法不能停不下来(停不下来这不没了!),所以我们要明确它的终止条件。也就是说,我们要能知道当参数为何值时,递归结束,并且我们能直接知道这个参数的返回值。例:

// 算 n 的阶乘(假设n不为0)
int factor(int 1){
        return 1;
}

对吧,我们可以很清楚地知道,当n = 1的时候,n的阶乘就等于1,那是不是就只能取值 n = 1呢?当然不是。

如果你知道任意参数的返回结果,你就可以把它设置为结束条件!

例如:

// 算 n 的阶乘(假设n不为0)
int factor(int 3){
        return 6;

3的阶乘就是6嘛~,理想情况下当然可以把n = 3作为结束条件(此时 n > 3),当然我这里的取值都是理想状态,在代码中还是要严谨一些的。

<3>等价关系式

这一步就是重点啦,什么叫做大事化小,小事化了,说的就是这个!一步步深入,不断缩小参数范围,直到遇到终止条件!
比如我们上面的这个题,我们想要求 n! ,那么 n! = n * (n - 1)! , (n - 1)! = (n - 1)*(n - 2)!..以此类推
换到上面的题目中,就是:

return n *factor(n-1);

那么,完整的方法如下:

public static int factor(int n) {
 if (n == 1) {
	 return 1;
 }
 	 return n * factor(n - 1); //此时调用函数自身
}

我这里设置了参数为 1 作为终止条件,当然其他参数也可以,根据n的取值来确定。

三丶递归案例分析

感觉自己感刚刚学会开小三轮,就要被逼上路了,而且这个小破路还是山路,笔者的未来的计划就是成为造轮子的大佬,然后开着飞机飞,这多有B格!!芜湖起飞~

案例一: 按顺序打印一个数字的每一位(例如 1234 打印出 1 2 3 4)

其实如果说是只能用循环来正序打印,笔者自己尝试过,真挺麻烦!!但是用递归,就方便很多。
三板斧走起:

第一步:明确函数自身目的—打印数字每一位

public static void print(int num) {
}

第二步: 明确终止条件—最后一位数字打印完成就结束

这里的话,笔者想提一下笔者做题时候总结出来的小经验:

如果一个整形数字想要去掉最后一位:就 /10 ,如果整数数字想得到最后一位:就 %10
所以结束条件就是 num / 10 == 0的时候,就剩最后一位啦,这一位打印结束。就不能再继续打印了

public static void print(int num) {
 if(a < 9) {
           System.out.print(a % 10 + " ");
       }
}

第三步:等价关系式
这一步的话,明确过程到底干了什么,就像这一题中,一边输出最后一位数,一边给自身赋值除去最后一位数字的其余数:

 if(a < 9) {
           System.out.print(a % 10 + " ");
       }else {
           print(a / 10);
           System.out.print(a % 10 + " ");

案例二:递归求 1 + 2 + 3 + … + 10

很简单,三板斧!!!!

第一步:明确函数自身目的—求和

  //求和
  public static int sum(int a){
     
    }

第二步: 明确终止条件—n = 1的时候,就没数字可以加了

  //求和
  public static int sum(int a){
        if(a == 1){
            return 1; 
        }
    }

第三步:等价关系式
这里的话说起来有点绕,就是 10 + 9+…+1 = 10 + (9 + … + 1)= 10 + 9 + (8 + … + 1)…

如下:

 public static int sum(int a){
        if(a == 1){
            return 1;
        }
        return a + sum(a - 1);
    }

笔者认为递归其实最难得点就在第三步和其中的细节把控,多少次因为一个变量设置不到位就被一直卡到死。

案例三:求斐波那契数列的第 N 项

什么叫做斐波那契数列,就是一个数列从第三项开始,任意一项等于前两项之和:1 ,1, 2 ,3 ,5 ,8…

第一步:明确函数自身目的—求n项数字

//这里是求斐波那契数列第n项
public static int fib(int n) {

}

第二步: 明确终止条件—n = 1或者 n = 2的时候,就停止计算了

//这里是求斐波那契数列第n项
public static int fib(int n) {
	if(a == 1 || a == 2){
            return 1;
        }
}

第三步:等价关系式

任意一项都等于前两项之和,也就是 fib(n) = fib (n - 1) + fib (n -2),而 fib(n-1) = fib( n - 2) + fib( n - 3),fib(n - 2) = fib( n - 3) + fib ( n - 4)…

//这里是求斐波那契数列第n项
public static int fib(int n) {
	if(a == 1 || a == 2){
            return 1;
        }
        return fib(a - 2) + fib(a - 1);
}

PS:关于斐波那契数列的进阶—迭代

在上面的案例三种,我们可以发现,如果说当n取值过大的之后,需要等很长很长一段时间后答案才会出来,甚至可以说出不来,这是为什么呢?

在这里插入图片描述
由图可以看出,每进行一层,运算的量都是呈2的指数倍上升,这是一个很可怕的事情,当n数字小的时候,还能用递归,数字大了呢??所以就不行了。
那么我们怎么办呢?

递归是从上到下,我们可以从下到上呀!,然后每个位数就执行一次,这种从下到上的思想叫做迭代,也可以叫做递推

那么具体该怎样实现呢?很简单,因为每一项的前两项之和等于其本身,所以,三板斧走起:

第一步—明确自身目的—求第n项和

public static int fib(int n) {
	
}

第二步—明确终止条件—当求到第n项时停止计算停止计算

       for (int i = 1; i <= n; i++) {
                
            }
        }
        return res;

第三步—等价关系式—每一项等于前两项相加

这一步较为特殊,因为第一项和第二项前面没有两项,所以真正应该从第三项算起,前两项的话要拉出来特别声明

 public static int fab(int n){
        int res = 0;
        int key1 = 1;
        int key2 = 1;
        if(n == 1 || n == 2){
          return 1;
        }else{
            for (int i = 3; i <= n; i++) {
                res = key1 + key2;
                key1 = key2;
                key2 = res;
            }
        }
        return res;
    }

综上,就是关于在这一章节递归的应用,希望大家可以指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值