Day20--递归

Day20--递归

A 方法调用 B 方法容易理解,

递归就是 A 方法调用 A 方法,即自己调用自己。

利用递归可以用简单程序解决复杂问题,通常把大型复杂问题层层转化为与原问题相似的规模较小问题求解,递归策略用少量程序描述解题过程所需多次重复计算,大大减少程序代码量。递归的能力在于用有限语句定义对象的无限集合。

递归结构包括两个部分:

  • 递归头,即什么时候不调用自身方法,没有头会陷入死循环;
  • 递归体,即什么时候需要调用自身方法。

没有递归头的示例:

​ 创建test方法,方法体是:调用test方法

package com.liu.www.method;

public class Demo05 {
    public static void main(String[] args) {
        Demo05 demo05 = new Demo05();//非静态方法的调用,要创建类的对象
        demo05.test();

    }
    public void test(){
        test();      //没有递归头,会陷入死循环!!!!!
    }
}

递归图标:(左边的)

image-20241020150641924

例子1:创建能够计算阶乘的方法

package com.liu.www.method;
//计算阶乘
//1!=1
//5!=5*4*3*2*1
public class Demo06 {
    public static void main(String[] args) {
        System.out.println(f(5));
    }
    public static int f(int i){
        if(i==1){
            return 1;           //递归头f(1),程序进行到f(1)就不再进行
        }else{
            return i*f(i-1);
        }
    }
    
    
    
    /*
    f方法解释:
    当i=5时,
    f(5)=5*f(4)
            f(4)=4*f(3)
                    f(3)=3*f(2)
                            f(2)=2*f(1)
                                     f(1)=1
     */
}

由例子可知,计算f(5),就要计算f(4)、f(3)、f(2)、f(1)。计算的流程为:

f(5)--->f(4)--->f(3)--->f(2)--->f(1)--->f(2)--->f(3)--->f(4)--->f(5)

image-20241020153305443

奇怪的现象:

上面的f方法,当我输入i=100时,输出结果为0。这是咋回事?

原因:

计算 100 的阶乘结果为 0 是因为整数类型的范围限制。

在 Java 中,int类型能表示的数据范围是有限的。当计算较大的阶乘时,结果很容易超出int类型的取值范围,导致数据溢出,最终结果变为 0。

递归只对基数小的例子有用

错误的案例:

public class Exercise {
    public static void main(String[] args) {
        //例子1:创建能够计算阶乘的方法
        Exercise exercise = new Exercise();
        exercise.acculate(3);
    }

    public int acculate(int a){
        int result=0;
        if (a < 0) {
            System.out.println("请输入大于0的数");
        }else {
            if(a==0||a==1){
                result=1;
            }else {
                result=a*acculate(a-1);
                System.out.println(result);
            }
        }return result;
    }


}



我的代码有问题,请帮我解决

以下是对你提供代码中存在问题的分析以及相应的修改建议:

存在的问题

  1. 逻辑错误 - 初始值设定问题
    acculate 方法中,你将 result 初始值设为 0,但对于阶乘计算来说,这是不正确的。阶乘的初始值(当 n = 0n = 1 时)应该是 1,因为 0! = 11! = 1,所以初始值设定为 0 会导致计算结果错误。
  2. 逻辑错误 - 多余的输出语句
    else 分支中(计算 n > 1 情况的阶乘时),有 System.out.println(result); 这一语句,在递归计算阶乘的过程中,这样会多次输出中间结果,而通常我们期望的是只输出最终的阶乘结果,所以这个输出语句放在这里不合适,应该把它移到合适的位置(比如方法调用结束后在外部输出最终结果)或者干脆去掉(如果只是想返回结果供外部进一步使用)。
  3. 代码风格与效率相关 - 重复创建对象问题
    main 方法中通过 Exercise exercise = new Exercise(); 创建了类的实例来调用 acculate 方法,其实 acculate 方法是一个实例方法,对于这个简单的功能,将其定义为静态方法更合适,这样就不需要先创建类的实例了,可以直接通过类名调用,能使代码更简洁高效。

修改后的代码如下

public class Exercise {
    public static void main(String[] args) {
        // 例子1:创建能够计算阶乘的方法
        int result = acculate(3);
        System.out.println("3的阶乘结果是:" + result);
    }

    public static int acculate(int a) {
        int result = 1;
        if (a < 0) {
            System.out.println("请输入大于0的数");
            return -1; // 可以返回一个特殊值表示输入不符合要求
        } else {
            if (a == 0 || a == 1) {
                result = 1;
            } else {
                result = a * acculate(a - 1);
            }
            return result;
        }
    }
}

在上述修改后的代码中:

  • 首先把 acculate 方法定义为了静态方法,在 main 方法中可以直接通过类名 Exercise 调用它,省去了创建实例对象的步骤。
  • 然后将 result 的初始值修改为了 1,符合阶乘计算的初始值设定要求。
  • 去掉了递归过程中多余的输出语句,而是在 main 方法中输出最终想要展示的结果,这样使得输出更符合预期,只展示了最终计算出的阶乘值。同时对于输入不符合要求(小于 0 的数)的情况,返回了一个特殊值 -1 便于外部判断输入是否合法,你也可以根据实际需求调整这里返回表示异常情况的值以及相应的处理逻辑哦。

希望修改后的代码能满足你的需求,帮助你正确实现阶乘计算的功能呀。

posted @ 2024-10-20 15:43  1hahahahahahahaha  阅读(40)  评论(0)    收藏  举报