递归的逻辑是啥

Posted

技术标签:

【中文标题】递归的逻辑是啥【英文标题】:What is the logic of the recursion递归的逻辑是什么 【发布时间】:2015-08-06 06:16:59 【问题描述】:

这是我使用递归的阶乘代码。

class Factorial

    public static void main(String args[])
    
       Factorial f = new Factorial();
       System.out.println(f.fact(Integer.parseInt(args[0])));
    

    private int fact(int num)
    
        int result;
        if(num == 1)
             return 1;

        result = fact(num - 1) * num;
        return result;
    

现在运行这个程序,我这样做了

D:\>java Factorial 3

现在按照进入fact函数的逻辑,其中num = 3,所以会跳转到

result = fact(num - 1) * num;

这里会变成

result = fact(3 - 1) * num;

result = fact(2) * num;

在这一步中,我有点困惑它是否执行整个步骤,即

result = fact(num - 1) * num;

或者只是fact(num - 1)

按照逻辑,它应该做的就是调用fact函数。因此,程序的控制再次到达了 num = 2 的事实函数的开头。它会再次跳到

result = fact(num - 1) * num;

所以,它会变成

result = fact(2 - 1) * num;

result = fact(1) * num;

现在,它应该再次调用 fact 函数而不执行整个语法 & 再次到达 fact 方法的开头 num = 1。这一次将匹配 num == 1 并返回 1。现在它会返回到

result = fact(num - 1) * num;

所以,它会变成

result = fact(1 - 1) * num;

result = fact(0) * num;

现在接下来会发生什么?

我走对了吗?如果不是,那将是什么更正?

我不太清楚这个递归程序的流程。

【问题讨论】:

您是否尝试过在调试器中执行此操作并查看调用堆栈?老实说,您并不清楚您在问什么。 for num = 2 [..] So, it will become result = fact(1 - 1) * num; 你为什么会这样想? 在每个步骤中它执行fact(num - 1) 并通过再次调用相同的方法向前移动,但在最后一步控制向后移动以完成方法体 没有地方只计算fact(num - 1)而不乘以num 任何体面的调试器都可以做到这一点。免费下载 Eclipse 并以这种方式逐步执行代码... 【参考方案1】:

所以,它会变成

result = fact(1 - 1) * num;

不。对于num = 2

result = fact(num - 1) * num;

变成

result = 1 * num; // i.e. 1 * 2

fact 返回一个值,这意味着必须将整个调用替换为该值。 不知道为什么你甚至会认为num 会发生变化。您的代码中没有 num = ...

【讨论】:

【参考方案2】:

我在程序中添加了一些跟踪。执行它并查看输出。应该很容易理解。

package snippet;

class Factorial 
    public static void main(String args[]) 
        Factorial f = new Factorial();
        System.out.println(f.fact(Integer.parseInt("5")));
    

    private int fact(int num) 
        int result;
        if (num == 1)
            return 1;

        result = fact(num - 1) * num;
        System.out.println("fact(" + num + ") = " + result + " = fact(" + (num - 1) + ") * " + num);
        return result;
    

事实(2) = 2 = 事实(1) * 2 事实(3) = 6 = 事实(2) * 3 事实(4) = 24 = 事实(3) * 4 事实(5) = 120 = 事实(4) * 5 120

【讨论】:

【参考方案3】:

您的逻辑是正确的,但您犯了 3 个基本错误。 如果我们以你为例; 首先你运行程序

D:\>java Factorial 3

那么您就有了第一个错误,因为根据逻辑,所有“num”都必须替换为“3”。所以你得到:

result = fact(3 - 1) * 3;

即:

result = fact(2)*3;

那么我们有第二个错误,因为根据fact(num)的定义,

fact(2) = fact(2-1)*2

所以我们实际上有

result = (fact(2-1)*2)*3

中评估
result = (fact(1)*2)*3

这里是第三个错误,因为再次根据 fact(num) 定义:fact(1) = 1 而不是fact(1) = fact(1-1)*1 所以我们终于有了:

result = ((1)*2)*3

更明确地说,如果您遵循调试器中的所有调用顺序,您将得到类似这样的内容(我将变量的值放在括号中):

   private int fact(num3)
    
        int result;
        if(num3== 1)
             return 1;

        result = fact(num3 - 1) * num3;

            private int fact(num3-1)
            
                int result;
                if(num3-1== 1)

                result = fact(num3-1 - 1) * num3-1;

                    private int fact(num3-1-1)
                    
                        int result;
                        if(num3-1-1== 1)
                             return 1;
                    

                return result1*3-1;
            
        return result1*3-1*3;
    

【讨论】:

【参考方案4】:

除非我们达到停止条件:

fact(num) = fact(num - 1) * num;

因此:

fact(3) = fact(3 - 1) * 3;

记住 fact(1) = 1(来自 fact() 方法早期的 if 语句):

fact(3) = fact(2) * 3;
fact(2) = fact(1) * 2;
fact(1) = 1;

替换每个元素:

fact(3) = 1 * 2 * 3;

递归用于反复深入进程,直到遇到停止条件 - 在这种情况下,当 num = 1 时。

【讨论】:

【参考方案5】:

调用 f.fact(3) 正在通过以下步骤扩展:

1. result = fact(3 - 1) * 3 = fact(2) * 3
2. result = (fact(2 - 1) * 2) * 3 = (fact(1) * 2) * 3
3. result = 1 * 2 * 3 because fact(1) returns 1.

【讨论】:

【参考方案6】:

您的实现是正确的,但它永远不会达到fact(1-1) * 1 状态,因为您从if(num == 1) 的方法返回。

num 变量仅限于方法参数的范围。因此,每次调用fact 方法num 变量都会被分配一个新值(即num-1),并且仅限于该参数范围。所以当fact(num-1) 返回时,num 的值将是原始值,而不是num-1

【讨论】:

【参考方案7】:

你的例子流程是这样的 步骤 1. 事实(3)*3; //调用num值为3的函数 步骤 2. 事实(2)*2; //再次使用 num=2 调用 fact() 方法 步骤 3. 事实(1)*1; //现在将匹配 num == 1 并返回 1。 一世。例如, 1 * 1 = 1; //现在,将分别执行步骤 2 和 1 第 2 步。1 * 2 = 2; 第 1 步。2 * 3 = 6;

所以,最终答案将是 6注意:在第 3 步中,值是 返回,所以它不会再调用 this result = fact(0) * num; //你提到的问题。

【讨论】:

以上是关于递归的逻辑是啥的主要内容,如果未能解决你的问题,请参考以下文章

计划递归解决问题的最佳方法是啥?

递归思维的算法是啥? (关于具体例子)

在Java中递归反转字符串的最佳方法是啥?

在标题搜索路径中检查“递归”是啥意思

C语言详解:函数递归专题

设计生成所有 n 位数字组合的递归函数的最佳方法是啥?