Java 让这种带记忆的递归斐波那契更快?
有没有办法让这个程序运行得更快?它已经比我尝试制作的HashMap版本快了,但根据我提交的位置,在45点左右仍然太慢。我能做些什么改进吗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;
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
保存是有效的,并且符合数组仅使用sizenum
@Andreas创建的事实,因为它更清晰、明显,并且符合将值保存在缓存[参数]
而不是缓存的一般记忆模式[其他一些可能会节省大量8字节内存的值]
但在n-1
处保存并非“错误”。可能是非标准的。可能不是最理想的。但不是错的。@Andrea在代码审阅时我肯定会说这是错的,因为这会使理解和调试变得更加困难,毫无收获。为什么OP会保存到错误的索引?OP永远不会保存到n=0
,所以保存在n-1
是有效的,并且符合以下事实:数组是使用sizenum
@Andreas创建的,因为它更清晰、更明显,并且符合将值保存在cache[参数]
而不是cache[其他一些可能保存多达8字节内存的值]
的一般记忆模式,但保存在n-1
并不是“错误的”。可能是非标准的。可能不是最理想的。但没有错。@Andrea在代码审查时,我肯定会说这是错的,因为这会使理解和调试变得更加困难,毫无益处。尽管OP故意没有为n=0
,而是保存在n-1
,所以数组只需要按大小创建num
。您的代码只会得到ArrayIndexOutOfBoundsException
,因为您更改了保存的索引位置。@Andreas在创建我的解决方案时,我先在方法顶部添加了一行以使用缓存。我确实得到了一个AIOOBE,因为最终会调用FIBOUN(0)
。因此,“减一”在阵列中保存一个空间不正确。另一种方法是在基本情况之后检查缓存。因此,您的错误是在n==0
检查之前添加了缓存检查,并决定以需要更多更改的方式进行修复,而不仅仅是翻转检查。@Andreas我决定以更易于理解和可读的方式修复代码。我的目标不是以尽可能少的更改来修复代码,而是修复以最容易理解、可读的方式显示代码。对我来说,数组的索引i
storefibo(i)更有意义
。可能OP故意没有保存为n=0
,而是保存在n-1
,因此只需要使用sizenum
创建数组。您的代码只会得到ArrayIndexOutOfBoundsException
,因为您更改了保存的索引位置。@Andreas在创建解决方案时,我添加了使用首先在方法顶部缓存。我确实得到了一个AIOOBE,因为最终会调用fibo(0)
。因此,在数组中保存一个空间的“负一”是不正确的。另一种方法是在基本情况之后检查缓存。因此,您的错误是在n==0
检查之前添加了缓存检查,并决定以需要更多更改的方式进行修复,而不仅仅是翻转检查。@Andreas我决定以更易于理解和可读的方式修复代码。我的目标不是以尽可能少的更改来修复代码,而是修复以最容易理解、可读的方式显示代码。对我来说,数组的索引i
storefibo(i)
更有意义。