【问题标题】:Code to get sums made of a fibonacci number获取斐波那契数的总和的代码
【发布时间】:2021-06-06 12:25:27
【问题描述】:

我正在尝试制作一个简单的递归代码来计算斐波那契级数的总和,但我不知道如何使计数器正常工作,这是我的代码:

public static long fibonacciRecursiveHits(int n,long sum) 
{
    if (n>1)
    {
        sum++;
        sum =  fibonacciRecursiveHits(n-1,sum) + fibonacciRecursiveHits(n-2,sum);
    }
    return sum;
}

例子:

Input: 4
Correct Output: 4 //The number of sums
My Output: 12

【问题讨论】:

  • 你有没有通过代码,或者更好的是,用铅笔和纸“玩电脑”来追踪执行路径?想想sum 在进入时发生了什么,以及当它递归传入、递增,然后再次相加时。
  • @DaveNewton 是的,这就是我通常做的,但我不知道如何计算每个递归调用的总和,因为如果我使用 sum,它会产生:1(第一个总和)+2(第一个加递归的总和),如果我在 sum 参数中引入 0 它没问题,但总是返回 0,因为最后一个递归调用总是读取 n 是
  • 如果运行时很重要,不要递归地实现这个函数——函数调用的数量在n 中呈指数增长。仅仅因为您想计算这些和的递归性质,您不必递归地实现它。例如,您可以实现从0n 的循环,并将中间结果存储在一个数组中以重复使用它并避免(指数)冗余工作。或者更好的是,考虑一下并在n 中明确制定序列。

标签: java recursion math fibonacci


【解决方案1】:

您的问题是您正在计算 n 的总和数,并且您将其添加到 n+1 和 n+2 的总和中,这使您多次计算它们。

简单的解决方案:返回总和数

只需计算 n 的总和数,不要将它们传递下去。试试这个例子:

public static long fibonacciRecursiveHits(int n)
{
    if (n>1)
    {
        return  fibonacciRecursiveHits(n-1) + fibonacciRecursiveHits(n-2) + 1;
    } else {
        return 0;
    }
}

我们在这里做什么:如果 n > 1,我们计算 n-1 的所有总和加上 n-2 的总和加上这个总和(1 总和)。

替代方案:传递参数

如果你想将 sum 作为参数传递并递归更新它,你可以,但并非没有技巧,因为 Java 是按值传递,这意味着如果你修改 sum in你的函数,它不会为调用者修改。 有几种方法可以解决此问题。

  1. 创建一个包含int sum 的对象并将该对象向下传递
  2. 创建一个静态变量 sum,以便您可以在类中的任何位置修改它
  3. 创建一个包含一个元素的数组并将其向下传递
  4. this answer中描述的其他方式

这是一个关于如何使用选项 3 的示例:

public static void fibonacciRecursiveHits(int n, long[] sum)
{
    if (n>1)
    {
        sum[0]++;
        fibonacciRecursiveHits(n-1, sum);
        fibonacciRecursiveHits(n-2, sum);
    }
}

发生的情况是每次调用求和都会增加总和。

现在你这样称呼它:

    long[] sum = {0};
    fibonacciRecursiveHits(4, sum);
    System.out.println(sum[0]); //sum[0] contains your result

迭代解决方案

上述递归解决方案的问题是它们具有指数运行时间 O(2^n),这意味着在中到大型输入上会非常慢。另一种方法是迭代地构建结果并将它们保存在数组中(动态编程)。这将运行时间减少到 O(n)。

public static long fibonacciRecursiveHits(int n)
{
    long[] sums = new long[n+1];
    // sums[0] and sums[1] are both initialized to 0
    for(int i = 2; i <= n; i++){
        sums[i] = sums[i-2] + sums[i-1] + 1;
    }
    return sums[n];
}

【讨论】:

  • 该死,这太容易了 :( ,难道没有一种可能的方法来使用该 sum 参数,因为结果的串联对吗?
  • 你可以传递一个参数,但它有点棘手,因为你不能在 Java 中传递对原语的引用(就像你可以在 C 中做的那样)。我更新了我的答案以解释您如何做到这一点
  • 非常感谢!非常感谢您的解释,我不知道 Java 的传递值
  • 在您的第一个示例中,您的 else 块是多余的。只需返回 0。
  • 我同意这不是必需的,但老实说,这是品味和风格的问题。我通常自己不会在提前返回后写 else 分支(以尽量减少缩进),但我认为对于编程新手来说,这有点不太明显,我相信 OP 是基于 OP 的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-21
  • 1970-01-01
  • 1970-01-01
  • 2015-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多