Java 让这种带记忆的递归斐波那契更快?

Java 让这种带记忆的递归斐波那契更快?,java,recursion,fibonacci,memoization,Java,Recursion,Fibonacci,Memoization,有没有办法让这个程序运行得更快?它已经比我尝试制作的HashMap版本快了,但根据我提交的位置,在45点左右仍然太慢。我能做些什么改进吗 import java.util.Scanner; public class Fibo { static long[] cache; static long ans; public static long fibo(int n) { if (n == 0) return 1;

有没有办法让这个程序运行得更快?它已经比我尝试制作的HashMap版本快了,但根据我提交的位置,在45点左右仍然太慢。我能做些什么改进吗

import java.util.Scanner;

public class Fibo {
    static long[] cache;
    static long ans;

    public static long fibo(int n) {
        if (n == 0) 
            return 1;
        if (n < 2) 
            ans = 1;
        else
            ans = fibo(n - 1) + fibo(n - 2);
        cache[n - 1] = ans;
        return ans;

    }

    public static void main(String[] args) {
            Scanner input = new Scanner(System.in);
            System.out.println("test");
            int num = input.nextInt();
            input.close();
            cache = new long[num];
            long ans = fibo(num);
            System.out.println(ans);
    }
}
import java.util.Scanner;
公共级Fibo{
静态长[]缓存;
静态长臂;
公共静态长fibo(整数n){
如果(n==0)
返回1;
if(n<2)
ans=1;
其他的
ans=fibo(n-1)+fibo(n-2);
高速缓存[n-1]=ans;
返回ans;
}
公共静态void main(字符串[]args){
扫描仪输入=新扫描仪(System.in);
系统输出打印(“测试”);
int num=input.nextInt();
input.close();
缓存=新长[num];
长ans=fibo(num);
系统输出打印LN(ans);
}
}

您正在尝试在缓存中存储答案,但没有使用它。在进行任何其他计算之前,请检查缓存。另外,当您到达
fibo(0)
时,您将得到一个
ArrayIndexOutOfBoundsException
,因为您正在减去一个。删除减法运算并增加数组的大小以解释它

public static long fibo(int n) {
    // Try cache first.
    if (cache[n] != 0) return cache[n];
    if (n == 0) 
        return 1;
    if (n < 2) 
        ans = 1;
    else
        ans = fibo(n - 1) + fibo(n - 2);
    // Don't subtract one.
    cache[n] = ans;
    return ans;
}

您正试图在缓存中存储答案,但没有使用它。在进行任何其他计算之前,请检查缓存。另外,当您到达
fibo(0)
时,您将得到一个
ArrayIndexOutOfBoundsException
,因为您正在减去一个。删除减法运算并增加数组的大小以解释它

public static long fibo(int n) {
    // Try cache first.
    if (cache[n] != 0) return cache[n];
    if (n == 0) 
        return 1;
    if (n < 2) 
        ans = 1;
    else
        ans = fibo(n - 1) + fibo(n - 2);
    // Don't subtract one.
    cache[n] = ans;
    return ans;
}

您可以通过实际使用缓存的值来加快速度:

public static long fibo(int n) {
    if (cache[n] > 0) {
        return cache[n];
    }
    ...
    cache[n] = ans; // you are saving at the wrong index
    ...
}

虽然在O(n)处使用memonization是“快”的,但是有一个mathy O(log n)解决方案是超快的。

您可以通过实际使用缓存值来加快速度:

public static long fibo(int n) {
    if (cache[n] > 0) {
        return cache[n];
    }
    ...
    cache[n] = ans; // you are saving at the wrong index
    ...
}

虽然在O(n)处使用memonization是“快”的,但是有一个mathy O(log n)解决方案是超快的。

您从来没有在
缓存中执行过任何查找,或者我遗漏了什么吗?Fibo()只从主方法调用一次,缓存从未真正使用过您从未在
cache
中执行过任何查找,或者我遗漏了什么?从主方法只调用了一次Fibo(),缓存从未真正使用过为什么OP保存到错误的索引?OP永远不会为
n=0
保存,因此在
n-1
保存是有效的,并且符合数组仅使用size
num
@Andreas创建的事实,因为它更清晰、明显,并且符合将值保存在
缓存[参数]
而不是
缓存的一般记忆模式[其他一些可能会节省大量8字节内存的值]
但在
n-1
处保存并非“错误”。可能是非标准的。可能不是最理想的。但不是错的。@Andrea在代码审阅时我肯定会说这是错的,因为这会使理解和调试变得更加困难,毫无收获。为什么OP会保存到错误的索引?OP永远不会保存到
n=0
,所以保存在
n-1
是有效的,并且符合以下事实:数组是使用size
num
@Andreas创建的,因为它更清晰、更明显,并且符合将值保存在
cache[参数]
而不是
cache[其他一些可能保存多达8字节内存的值]
的一般记忆模式,但保存在
n-1
并不是“错误的”。可能是非标准的。可能不是最理想的。但没有错。@Andrea在代码审查时,我肯定会说这是错的,因为这会使理解和调试变得更加困难,毫无益处。尽管OP故意没有为
n=0
,而是保存在
n-1
,所以数组只需要按大小创建
num
。您的代码只会得到
ArrayIndexOutOfBoundsException
,因为您更改了保存的索引位置。@Andreas在创建我的解决方案时,我先在方法顶部添加了一行以使用缓存。我确实得到了一个AIOOBE,因为最终会调用
FIBOUN(0)
。因此,“减一”在阵列中保存一个空间不正确。另一种方法是在基本情况之后检查缓存。因此,您的错误是在
n==0
检查之前添加了缓存检查,并决定以需要更多更改的方式进行修复,而不仅仅是翻转检查。@Andreas我决定以更易于理解和可读的方式修复代码。我的目标不是以尽可能少的更改来修复代码,而是修复以最容易理解、可读的方式显示代码。对我来说,数组的索引
i
store
fibo(i)更有意义
。可能OP故意没有保存为
n=0
,而是保存在
n-1
,因此只需要使用size
num
创建数组。您的代码只会得到
ArrayIndexOutOfBoundsException
,因为您更改了保存的索引位置。@Andreas在创建解决方案时,我添加了使用首先在方法顶部缓存。我确实得到了一个AIOOBE,因为最终会调用
fibo(0)
。因此,在数组中保存一个空间的“负一”是不正确的。另一种方法是在基本情况之后检查缓存。因此,您的错误是在
n==0
检查之前添加了缓存检查,并决定以需要更多更改的方式进行修复,而不仅仅是翻转检查。@Andreas我决定以更易于理解和可读的方式修复代码。我的目标不是以尽可能少的更改来修复代码,而是修复以最容易理解、可读的方式显示代码。对我来说,数组的索引
i
store
fibo(i)
更有意义。