java库类似于c ++ map

时间:2015-12-15 16:05:56

标签: java c++ stl hashmap

要使用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中使用LinkedHashMapTreeMap尝试了此代码,但都提供了相同的错误。

我必须使用哪个类与c ++中的map相同?

请有人解释map在c ++中的工作原理。

修改
查看javac++中代码的输出 c ++:c++ code
java:java code

2 个答案:

答案 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;
}

Taken from here.

您还可以查看this question以获取其他示例。