计算n的阶乘-递归与迭代之间的转换

n的阶乘是指从1连乘到n的结果,通常用符号n!表示。例如,3的阶乘表示为3!,计算过程如下:

3! = 3 × 2 × 1 = 6

一般地,n的阶乘可以用递归或迭代的方式计算,公式为:

n! = n × (n-1) × (n-2) × ... × 2 × 1

阶乘在数学和计算机科学中都有广泛的应用,例如在组合数学、排列组合、概率统计等领域。

那么用java代码来实现,有哪些方式呢(顺便扩展一下1!+2!+......+n!)

第一种:迭代,这种是最直观最容易理解的

//普通的迭代方式计算阶乘
    private long factorial(int n) {
        long factorial = 1;
        while (n > 1) {
            factorial = factorial * n;
            n--;
        }
        return factorial;
    }

    @Test
    public void factorial() {
        System.err.println(factorial(1));
        System.err.println(factorial(2));
        System.err.println(factorial(3));
        System.err.println(factorial(4));
        System.err.println(factorial(5));
    }

    //普通的迭代方式计算阶乘相加
    private long factorialSum(int n) {
        long sum = 0;
        while (n >= 1) {
            sum = sum + factorial(n);
            n--;
        }
        return sum;
    }

    @Test
    public void factorialSum() {
        System.err.println(factorialSum(1));
        System.err.println(factorialSum(2));
        System.err.println(factorialSum(3));
        System.err.println(factorialSum(4));
        System.err.println(factorialSum(5));
    }

第二种:递归,只要n不等于1,一直调用自身:

 //递归计算阶乘
    private long recursionFactorial(int n) {
        if (n == 1) {
            return n;
        } else {
            return n * recursionFactorial(n - 1);
        }
    }

    @Test
    public void recursionFactorial() {
        System.err.println(recursionFactorial(1));
        System.err.println(recursionFactorial(2));
        System.err.println(recursionFactorial(3));
        System.err.println(recursionFactorial(4));
        System.err.println(recursionFactorial(5));
    }

    //递归计算阶乘之和
    private long recursionFactorialSum(int n) {
        if (n == 1) {
            return n;
        } else {
            return recursionFactorial(n) + recursionFactorialSum(n - 1);
        }
    }

    @Test
    public void recursionFactorialSum() {
        System.err.println(recursionFactorialSum(1));
        System.err.println(recursionFactorialSum(2));
        System.err.println(recursionFactorialSum(3));
        System.err.println(recursionFactorialSum(4));
        System.err.println(recursionFactorialSum(5));
    }

第三种:使用栈或者队列来实现,递归的本质是在jvm层面的方法栈上创建栈帧来缓存中间结果,那么我们可以换一种思路,只要能把中间结果缓存起来,就可以不用递归了,其本质其实还是迭代:

//Stack栈方式计算阶乘
    private long stackFactorial(long n) {
        Stack<Long> stack = new Stack<>();
        stack.push(n);
        long result = 1;
        while (!stack.isEmpty()) {
            Long pop = stack.pop();
            result = result * pop;
            if (n > 1) {
                n--;
                stack.push(n);
            }
        }
        return result;
    }


    @Test
    public void stackFactorial() {
        System.err.println(stackFactorial(1));
        System.err.println(stackFactorial(2));
        System.err.println(stackFactorial(3));
        System.err.println(stackFactorial(4));
        System.err.println(stackFactorial(5));
    }

    //Stack栈方式计算阶乘之和
    private long stackFactorialSum(long n) {
        Stack<Long> stack = new Stack<>();
        stack.push(stackFactorial(n));
        long result = 0;
        while (!stack.isEmpty()) {
            Long pop = stack.pop();
            result = result + pop;
            if (n > 1) {
                n--;
                stack.push(stackFactorial(n));
            }
        }
        return result;
    }

    @Test
    public void stackFactorialSum() {
        System.err.println(stackFactorialSum(1));
        System.err.println(stackFactorialSum(2));
        System.err.println(stackFactorialSum(3));
        System.err.println(stackFactorialSum(4));
        System.err.println(stackFactorialSum(5));
    }

总结:某些递归是可以通过迭代来实现的,那么递归和迭代能够相互转换的条件是什么呢,我们来看看不同的AI模型的回答

chatgpt:

 讯飞星火:

 腾讯混元:

 百度AI:

 阿里通义千问:(这个截图不全,就贴文字了)

递归与迭代可以相互转换的条件通常基于问题本身的特性。在某些情况下,一个使用递归实现的问题可以通过重新组织代码和使用循环结构(如for、while等)来实现迭代版本。反过来,一些用迭代实现的问题也可能通过引入函数调用自身的方式来实现递归版本。

要判断一个问题是否可以递归与迭代之间转换,可以考虑以下几点:

  1. 可分解性:问题必须能够被分解为更小的同类子问题,这是递归的核心思想。同样,如果问题可以用循环来处理每个元素或状态,则可能适合迭代。

  2. 基本情况的存在:对于递归来说,需要存在一个或多个基本的情况,在这些情况下,不需要进一步递归。对于迭代来说,这通常是循环结束的条件。

  3. 合并子结果:无论是递归还是迭代,都需要一种方式将子问题的结果合并到整个问题的答案中。

  4. 问题规模的变化:在递归过程中,问题规模应该逐渐减小,最终达到基本情况。在迭代过程中,这通常表现为循环变量的变化。

  5. 空间和时间效率:虽然递归和迭代都可以解决同一问题,但它们的时间复杂度和空间复杂度可能会不同。在进行转换时,需要注意是否会影响算法的性能。

尽管大多数情况下递归与迭代可以相互转换,但也有一些特殊情况,比如涉及到特定数据结构(如树、图)的问题,或者一些复杂的动态规划问题,它们可能更适合于使用其中的一种方法,因为另一种方法可能会导致代码变得过于复杂且难以理解。因此,在实际编程中,选择哪种方法取决于具体问题以及对性能和代码可读性的要求。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值