【问题标题】:Recursion problem - is this solution correct, and is there a simpler one?递归问题 - 这个解决方案是否正确,是否有更简单的解决方案?
【发布时间】:2020-11-19 04:29:57
【问题描述】:

我是递归新手,我发现了以下 Java 问题:
编写一个获取整数 n 的函数,并打印数字 1!,2!,3!,...,n!。
这是我所做的,我想知道这是否是最简单的解决方案(我不确定,因为我使用“for”循环来做到这一点)。

public static void Print(int n) {
  if (n == 0) {
    System.out.print("1");
  } else {
    int temp = 1;
    for (int i = 1; i <= n, i++) {
      temp = temp * i;
    }
    Print(n-1);
    System.out.print(temp);
  }
}

顺便说一句,前面的练习是使用递归编写一个获取整数 n 并返回 n! 的函数。你认为我需要在这里使用它并打印它而不是计算温度(n!)并打印它吗? 谢谢!

【问题讨论】:

  • 您在发布的代码中有语法错误
  • @ButiriDan 谢谢,我修好了
  • 对于这个函数,你需要使用 long 来代替。因子会导致快速溢出,因为增长速度如此之快。
  • 这不是递归解决它的好方法
  • 同时使用递归和for循环没有多大意义。您可以使用任一解决问题。

标签: java recursion


【解决方案1】:

这是一个简单的递归解决方案:

  public static long factorial(long n) {
    if(n == 0 || n == 1) {
      System.out.print(1 + " ");
      return 1;
    }

    long result = n * factorial(n - 1);
    System.out.print(result + " ");
    return result;
  }

【讨论】:

  • 谢谢,但我还没学会什么是“长”,我才刚刚开始,练习应该只使用基本的东西
  • long 是一种数值类型,在溢出之前存储的位数比int 多。在这种情况下,它们是完全可以互换的,前提是 n!
  • long 只是像int 这样可以存储更大数字的原始数据类型。对阶乘使用int 会很快导致整数溢出。见docs.oracle.com/javase/tutorial/java/nutsandbolts/…
【解决方案2】:

您编写的内容有效,但是您正在重新计算一堆东西,并且您仍在使用for 循环,因为您可以递归地完成整个事情并且使用更少的代码。

假设您使用函数Print(int n) 卡住了,您可以编写更少的代码,并且只通过从1 向上递归计算每个阶乘并进行计算:

public static void Print(int n) {
    PrintHelper(1, n, 1);
}

private static void PrintHelper(int i, int n, long factorial) {
    if (i > n)
        return;

    factorial *= i;
    System.out.println(factorial);
    PrintHelper(i + 1, n, factorial);
}

这更容易阅读,更容易推理,并且避免了一遍又一遍地进行相同的计算。

在我上面发布的示例中,我正在做n 乘法。在您的示例中,您正在执行大约 n^2 / 2 乘法,因为您一次又一次地迭代每个数字(例如:1*2*3*...*50,然后 1*2*3*...*49,然后 1 *2*3*...*48, ...等)。

为了简洁起见,我编写的代码省略了错误检查,因为您可以轻松地向其中添加输入完整性检查。

【讨论】:

    【解决方案3】:

    没有递归

    int temp = 1;
    for (int i = 1; i <= 10; ++i) {
        temp *= i;
    }
    System.out.println(temp);
    

    递归就是你的循环

    public static void main(String[] args) {
        System.out.println(print(10));
    }
    
    public static long print(long n) {
        if (n == 0) {
            return 1;
        }
        return n * print(n - 1);
    }
    
    

    输出

    3628800
    

    【讨论】:

    • 这个问题有点不清楚,但我相信目的是打印n factorial,而不是从字面上打印n!
    • 这就是我现在对问题的理解,我认为我们需要打印值而不是 k!
    【解决方案4】:

    单行将如下所示:

    public static int factorial(int n) {
        return (n <= 2) ? n : n * factorial((n-1));
    }
    
    

    ternary operator 折叠 if 语句。然后使用递归,每个函数调用都成为阶乘函数中的一个因子,直到达到基本情况(n &lt;= 2):

    4 * 阶乘(3)

    4 * 3 * 阶乘(2)

    4 * 3 * 2

    【讨论】:

      【解决方案5】:

      使用递归来获得一个数的阶乘(之前的练习),这个方法看起来像

      long factorial(long n) {
          if (n > 0) {
              return n*factorial(n - 1);
          }
          return 1;
      }
      

      鉴于此,最好不要使用递归,而只使用循环来获取数字的阶乘,如下所示:

      long factorial(long n) {
          long factorial = 1;
          for (long i = 1; i <= n; i++) {
              factorial *= i;
          }
          return factorial;
      }
      

      如果你想要系列中的所有数字

      long[] factorials(long n) {
          long[] factorials = new long[n+1];
          long factorial = 1;
          for (long i = 1; i <= n; i++) {
              factorial *= i;
              factorials[n] = factorial;
          }
          factorials[0] = 1;
          return factorials;
      }
      

      如果只需要打印出来,方法就变成了

      void factorials(long n) {
          long factorial = 1;
          System.out.println(factorial); // 0!
          for (long i = 1; i <= n; i++) {
              factorial *= i;
              System.out.println(factorial);
          }
      }
      

      【讨论】:

        【解决方案6】:

        这会以一种不会使递归表达式更难阅读的方式添加打印。

        public class Fact {
        
            public static void main(String... args) {
                fact(5L);
                System.out.println();
            }
        
            static long fact(long n) {
                return print(
                    n == 0 || n == 1 ? 1 : n * fact(n - 1));
            }
        
            static long print(long i) {
                System.out.print(Long.toString(i));
                return i;
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-12-24
          • 2020-05-22
          • 2013-07-22
          • 1970-01-01
          • 2020-10-29
          • 1970-01-01
          相关资源
          最近更新 更多