1

To find nth fibonacci number using memoization I found one code which uses map in c++.

I have tried to convert this code in java but it fails .

code in 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));  
}   

I have tried same code in java using HashMap.

code in 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);
  }

but this code in java gives StackOverflowError.

I have tried this code using LinkedHashMap and TreeMap in java both gives same error.

Which class I have to use which works same as map in c++?

Please someone explain how map work in c++.

EDIT
look at the output of code in java and c++
c++: c++ code
java: java code

priyank
  • 35
  • 1
  • 2
  • 9
  • 1
    That is a really complicated way to implement this. Why not have a loop to record all the values which fit into a `long` in an array. It will take 3 ms and be not only faster but much simpler. – Peter Lawrey Dec 15 '15 at 16:24
  • i am solving this question http://www.spoj.com/problems/POWFIB/ – priyank Dec 15 '15 at 16:34
  • I have tried using matrix multiplication but it gives time limit exceed – priyank Dec 15 '15 at 16:34

2 Answers2

2

To memorize all the possible fibonacci numbers which fit into a long you can use a simple array.

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) {
}

prints

Took 0.648 seconds to build table of 100,000,000 fibonacci values

This would use 400 MB of memory for the array which is more efficient than any map implementation.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • input is in range of 10^8 – priyank Dec 15 '15 at 16:33
  • and number of test cases are around 10^5 – priyank Dec 15 '15 at 16:36
  • @priyank in that case you need to calculate the value using a formula. https://www.math.hmc.edu/funfacts/ffiles/10002.4-5.shtml There isn't enough memory to memorize that many values. BTW `long` won't store results above fib(92). – Peter Lawrey Dec 15 '15 at 16:36
  • 1
    question is to find nth fibinacci number mod 10^9+7. I have used %M in solution – priyank Dec 15 '15 at 16:40
  • @priyank the number of digits in fib(10^8) is approximately `20,898,764` so to memorize all these values you need approx 10^8 * 4 MB on average or 4 * 10 ^ 14 bytes or 400 TB. – Peter Lawrey Dec 15 '15 at 16:40
  • @priyank In that case you need 8 * 10^8 bytes or 800 MB as a `long[]` to store all the possible calculated Fibonacci values. This is far more practical. – Peter Lawrey Dec 15 '15 at 16:43
  • look at this solution http://ideone.com/sFrFVl I am trying to convert it into java but not able to convert function f() in java due to above mention problem – priyank Dec 15 '15 at 16:45
  • @priyank see my solution which memorizes every possible value in 0.7 seconds. – Peter Lawrey Dec 15 '15 at 16:48
1

A StackOverflowError happens when you have too many methods calls stacked, it's thrown by the virtual machine. It's not a HashMap problem at all.

From the docs:

Thrown when a stack overflow occurs because an application recurses too deeply.

You could either increase the stack size of your JVM by using the -Xss flag, or you could try to use a better algorithm, or review this one to check if it's really equivalent to the c++ version... But either way, I think you're just overcomplicating this, there are simpler ways of getting the same result.

You can also check this question on how a recursive fibonacci method looks like.


EDIT: Check this link, it shows how you can get the nth number using memoization and Java.

Also, check this question, there are lots of answers with different methods on how to get a large nth fibonacci number.


Another way of doing this

Use a List<Long> as a cache.

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.

You can also check this question for another example.

Community
  • 1
  • 1
Mauker
  • 11,237
  • 7
  • 58
  • 76
  • I think problem is map in c++ works different than Hashmap in java. I am novice to c++ so i dont know how map in c++ works – priyank Dec 15 '15 at 16:22
  • And **stackoverflowerror** is because of calling f(k+1) every time while in c++ code it doesn't give same error .. I dont understand why this happens in c++ – priyank Dec 15 '15 at 16:24
  • I believe that the only difference is that c++ `map` uses less memory than Java `HashMap`. – Mauker Dec 15 '15 at 16:25
  • look at this c++ implementation http://ideone.com/rTjjw6 . here printf in function is for debugging purpose .. it calls function two time only :) – priyank Dec 15 '15 at 16:56
  • while same function in java https://ideone.com/Yt59Pb continuesly calls it self for n=2 – priyank Dec 15 '15 at 17:03