给定斐波那契方法/函数,实现它并使其高效

时间:2016-07-08 22:55:48

标签: java fibonacci

嘿伙计们,在我的采访问题中,我得到了类似下面的内容。顺便说一下,这是我解决fib的代码。我想改进我的代码以消除可能最终在过程中重复的斐波那契序列的重复。例如,如果fib(1)和fib(1)重复两次,我该如何避免这种情况发生,因此程序可以前进到正在处理的唯一序列。

我真的想知道如何改进这段代码。我的解决方案如下,但是当我进行调试时,我觉得我很难理解真正发生的事情。

感谢。

public class Fib {

public static void main(String[] args) {

    System.out.print(fibonacci(14));
}

private static int fibonacci(int n) {

    int fibArray[] = new int[n];
    if (n <= 0) {
        return 1;
    } else if (n == 1) {
        return 1;
    } else {
        fibArray[0] = fibonacci(n - 1);
        fibArray[1] = fibonacci(n - 2);
        if (fibArray[0] == fibonacci(n - 1)) {
            return fibonacci(n - 1) + fibonacci(n - 2);
        } else if (fibArray[1] != fibonacci(n - 2)) {
            return fibonacci(n - 1) + fibonacci(n - 2);

        } else {
            return fibonacci(n - 1) + fibonacci(n - 2);
        }

    }
}

}

4 个答案:

答案 0 :(得分:2)

要解决第n个Fibonacci数,像你的答案那样的基本递归不是最好的方法。

有一个复杂的matrix方法来解决使用O(log(n))运行时和O(log(n))内存的Fibonacci。

如果你想要斐波纳契解决方案的性能和简洁性,这是一个简洁的公式(尽管这是记忆并且无法解决问题解决部分的采访): formula

这是一个Java方法实现:

public Long fibonacci(int n)
{
    double sqrt5 = Math.sqrt(5);

    int tmp1 = (int)(1+sqrt5)/2;
    int tmp2 = (int)(1-sqrt5)/2;

    return (long) Math.ceil((Math.pow(tmp1, n) - Math.pow(tmp2, n))/sqrt5);
}

此方法看起来是O(1),但它并不像Math.pow()O(log(n))那样。它使用O(1)内存。

答案 1 :(得分:1)

您需要存储计算后的值。如果存在值,则不再计算,只需使用它,否则计算并存储:

public class Fib {
    static int fibo[]=new int[100];

    public static void main(String[] args) {

        Arrays.fill(fibo, 0);
        System.out.print(fibonacci(24));
    }

    private static int fibonacci(int n) {
        if (n <= 0) 
            fibo[n]=0;
        else if (n == 1) 
            fibo[n]= 1;
        else if(fibo[n]==0)
            fibo[n]=fibonacci(n-1)+fibonacci(n-2);
        return fibo[n];

    }
}

答案 2 :(得分:1)

让我们稍微概括一下。

有许多技术可用于优化递归函数。以下是其中一些:

  1. 记忆:您可以使用相同的参数减少重复调用(昂贵的)函数f(n)的成本。这可以通过创建地图n - &gt;来完成。 f(n)并在拨打昂贵电话之前进行地图查询。

  2. 将递归转换为迭代。函数式编程语言的编译器通常会针对简单情况(尾调用)自动执行此操作。 Java编译器不会(出于技术原因偏离轨道)......但您可以在源代码级别进行相同的优化。

  3. 使用类似堆栈的数据结构将调用堆栈递归转换为迭代。这可能是您在Java中可以做的事情,以避免深度递归问题中的StackOverflowError异常,这些异常不适用于其他优化。

  4. 解决方案可能是解决重现关系,而不是尝试计算它。

  5. 显然,并非所有技术都适用于任何特定问题。

    其他答案给出了大多数方法的例子。

    • 方法#1 - @Dip
    • 方法#2 - @FirstStep
    • 方法#4 - @PhotometricStereo

答案 3 :(得分:0)

提到@PavelS。应该是类似于n是您的参数的内容:

    int a = 0;
    int b = 1;

    // In N steps compute Fibonacci sequence iteratively.
    for (int i = 0; i < n; i++)
    {
        int temp = a;
        a = b;
        b = temp + b;
    }
    return a;