要使用memoization查找第n个斐波纳契数,我发现一个代码在c ++中使用map
。
我试图在java中转换此代码,但它失败了。
c ++中的代码:
#include <bits/stdc++.h>
typedef long long int ll;
map<ll, ll> mp;
ll M = 1000000007;
long long fibonacci(long long n) {
if (mp.count(n))return mp[n];
long long k=n/2;
if (n%2==0) {
return mp[n] = fibonacci(k)*(fibonacci(k+1)+fibonacci(k-1)) % M;
} else {
return mp[n] = (fibonacci(k+1)*fibonacci(k+1) + fibonacci(k)*fibonacci(k)) % M;
}
}
int main()
{
mp[0]=mp[1]=1;
ll t;
scanf("%lld",&t);
printf("%lld\n",fibonacci(t));
}
我使用HashMap
在java中尝试过相同的代码。
java中的代码:
static HashMap<Long,Long> hm=new HashMap<Long,Long>();
static long f(long n) {
if (hm.containsKey(n)) return hm.get(n);
long k=n/2;
if (n%2==0) {
return hm.put(n,f(k)*(f(k+1)+f(k-1)) % M);
} else {
return hm.put(n, (f(k+1)*f(k+1) + f(k)*f(k)) % M);
}
}
public static void main(String[] args) throws IOException {
hm.put(1L,1L);
hm.put(0L,1L);
long b=f(2L);
}
但是java中的这段代码给出了StackOverflowError
。
我在java中使用LinkedHashMap
和TreeMap
尝试了此代码,但都提供了相同的错误。
我必须使用哪个类与c ++中的map
相同?
请有人解释map
在c ++中的工作原理。
答案 0 :(得分:2)
要记住适合long
的所有可能的斐波纳契数,你可以使用一个简单的数组。
static final int[] FIB = new int[100_000_000];
static final intM = 1000000007;
static {
long start = System.currentTimeMillis();
FIB[1] = FIB[2] = 1;
for (int i = 3; i < FIB.length; i++) {
int l = FIB[i - 1] + FIB[i - 2];
while (l >= M)
l -= M;
FIB[i] = l;
}
long time = System.currentTimeMillis() - start;
System.out.printf("Took %.3f seconds to build table of %,d fibonacci values%n", time/1e3, FIB.length);
}
public static long fibonacci(int n) {
return FIB[n];
}
public static void main(String[] args) {
}
打印
Took 0.648 seconds to build table of 100,000,000 fibonacci values
这将为阵列使用400 MB的内存,这比任何地图实现都更有效。
答案 1 :(得分:1)
当你有太多的方法调用堆叠时会发生StackOverflowError
,它会被虚拟机抛出。这根本不是HashMap
问题。
来自文档:
因应用程序递归而发生堆栈溢出时抛出 太深了。
您可以使用-Xss
标志来增加JVM的堆栈大小,或者您可以尝试使用更好的算法,或者查看此算法以检查它是否真的等同于c ++版本...但无论哪种方式,我认为你只是过于复杂,有更简单的方法来获得相同的结果。
您还可以查看this question递归斐波那契方法的样子。
编辑:检查this link,它显示了如何使用memoization和Java获取第n个数字。
另外,检查this question,对于如何获得大的第n个斐波纳契数,有很多不同方法的答案。
另一种方法
使用List<Long>
作为缓存。
private static List<Long> cache = new ArrayList<Long>();
/*
* Java Program to calculate Fibonacci numbers with memorization
* This is quite fast as compared to previous Fibonacci function
* especially for calculating factorial of large numbers.
*/
public static int improvedFibo(int number){
Integer fibonacci = cache.get(number);
if(fibonacci != null){
return fibonacci; //fibonacci number from cache
}
//fibonacci number not in cache, calculating it
fibonacci = fibonacci2(number);
//putting fibonacci number in cache for future request
cache.put(number, fibonacci);
return fibonacci;
}
您还可以查看this question以获取其他示例。