Recursive Fibonacci memoization

2019-01-10 21:51发布

I need some help with a program I'm writing for my Programming II class at universtiy. The question asks that one calculates the Fibonacci sequence using recursion. One must store the calculated Fibonacci numbers in an array to stop unnecessary repeated calculations and to cut down to the calculation time.

I managed to get the program working without the array and memorization, now I'm trying to implement that and I'm stuck. I'm not sure how to structure it. I've Googled and skimmed through some books but haven't found much to help me solve how to implement a solution.

import javax.swing.JOptionPane;
public class question2
{
static int count = 0;
static int [] dictionary;

public static void main(String[] args)
{

int answer;
int num = Integer.parseInt(javax.swing.JOptionPane.showInputDialog("Enter n:"));

javax.swing.JOptionPane.showMessageDialog(null, 
        "About to calculate fibonacci(" + num + ")");

//giving the array "n" elements
dictionary= new int [num];

if (dictionary.length>=0)
dictionary[0]= 0;

if (dictionary.length>=1)
dictionary[0]= 0;
dictionary[1]= 1;


//method call
answer = fibonacci(num);

//output
JOptionPane.showMessageDialog(null,"Fibonacci("+num+") is "+answer+" (took "+count+" calls)");
}



  static int fibonacci(int n)
  {
count++;

// Only defined for n >= 0
if (n < 0) {
  System.out.println("ERROR: fibonacci sequence not defined for negative numbers.");
  System.exit(1);
}

// Base cases: f(0) is 0, f(1) is 1
// Other cases: f(n) = f(n-1) + f(n-2)/
if (n == 0) 
{
  return dictionary[0];
}

else if (n == 1) 
{
  return dictionary[1];
}

else
return dictionary[n] = fibonacci(n-1) + fibonacci(n-2);



}

}

The above is incorrect, the end of my fib method is the main problem. I've no idea how to get it to add the numbers recursively to the correctly parts of the array.

10条回答
Ridiculous、
2楼-- · 2019-01-10 22:02

I believe you forget to actually look up stuff in your dictionary.

Change

else
    return dictionary[n] = fibonacci(n-1) + fibonacci(n-2);

to

else {
    if (dictionary[n] > 0)
        return dictionary[n];

    return dictionary[n] = fibonacci(n - 1) + fibonacci(n - 2);
}

and it works just fine (tested it myself :)

查看更多
够拽才男人
3楼-- · 2019-01-10 22:05
public static int fib(int n, Map<Integer,Integer> map){

    if(n ==0){
        return 0;
    }

    if(n ==1){
        return 1;
    }

    if(map.containsKey(n)){
        return map.get(n);
    }

    Integer fibForN = fib(n-1,map) + fib(n-2,map);
    map.put(n, fibForN);

    return fibForN; 

}

Similar to most solutions above but using a Map instead.

查看更多
\"骚年 ilove
4楼-- · 2019-01-10 22:05

Here is my implementation.

private static int F(int N, int[] A) {
    if ((N == 0) || (N == 1)) return N;
    if (A[N] != 0) return A[N];

    if ((A[N - 1] != 0) && (A[N - 2] != 0)) {
        A[N] = A[N - 1] + A[N - 2];
        return A[N];
    }

    if (A[N-2] != 0) {
        A[N] = A[N - 2] + F(N - 1, A);
        return A[N];
    }
    if (A[N-1] != 0) {
        A[N] = A[N - 1] + F(N - 2, A);
        return A[N];
    }
    A[N] = F(N-1, A) + F(N-2, A);
    return A[N];
}
查看更多
我欲成王,谁敢阻挡
5楼-- · 2019-01-10 22:06

You need to distinguish between already calculated number and not calculated numbers in the dictionary, which you currently don't: you always recalculate the numbers.

if (n == 0) 
{
  // special case because fib(0) is 0
  return dictionary[0];
}
else 
{
  int f = dictionary[n];
  if (f == 0) {
    // number wasn't calculated yet.
    f = fibonacci(n-1) + fibonacci(n-2);
    dictionary[n] = f;
  }
  return f;
}
查看更多
做自己的国王
6楼-- · 2019-01-10 22:07

Here is a fully-fledged class that leverages the memoization concept:

import java.util.HashMap;
import java.util.Map;

public class Fibonacci {

    public static Fibonacci getInstance() {
        return new Fibonacci();
    }

    public int fib(int n) {
        HashMap<Integer, Integer> memoizedMap = new HashMap<>();

        memoizedMap.put(0, 0);
        memoizedMap.put(1, 1);

        return fib(n, memoizedMap);
    }

    private int fib(int n, Map<Integer, Integer> map) {
        if (map.containsKey(n))
            return map.get(n);

        int fibFromN = fib(n - 1, map) + fib(n - 2, map);

        // MEMOIZE the computed value
        map.put(n, fibFromN);

        return fibFromN;
    }
}

Notice that

memoizedMap.put(0, 0);
memoizedMap.put(1, 1);

are used to eliminate the necessity of the following check

if (n == 0) return 0;
if (n == 1) return 1;

at each recursive function call.

查看更多
聊天终结者
7楼-- · 2019-01-10 22:14
int F(int Num){
int i =0;
int* A = NULL;
if(Num > 0)
{
 A = (int*) malloc(Num * sizeof(int));
}
else
 return Num;

for(;i<Num;i++)
 A[i] = -1;

return F_M(Num, &A);


}

int F_M(int Num, int** Ap){
int Num1 = 0;
int Num2 = 0;

if((*Ap)[Num - 1] < 0)
{
  Num1 = F_M(Num - 1, Ap);
  (*Ap)[Num -1] = Num1;
  printf("Num1:%d\n",Num1);
}
else
  Num1 = (*Ap)[Num - 1];

if((*Ap)[Num - 2] < 0)
{
  Num2 = F_M(Num - 2, Ap);
  (*Ap)[Num -2] = Num2;
  printf("Num2:%d\n",Num2);
}
else
  Num2 = (*Ap)[Num - 2];

if(0 == Num || 1 == Num)
{
 (*Ap)[Num] = Num;
 return Num;
}
else{
//  return ((*Ap)[Num - 2] > 0?(*Ap)[Num - 2] = F_M(Num -2, Ap): (*Ap)[Num - 2]  ) +     ((*Ap)[Num - 1] > 0?(*Ap)[Num - 1] = F_M(Num -1, Ap): (*Ap)[Num - 1]  );
  return (Num1 + Num2);
}

}

int main(int argc, char** argv){
int Num = 0;
if(argc>1){
sscanf(argv[1], "%d", &Num);
}

printf("F(%d) = %d", Num, F(Num));

return 0;

}
查看更多
登录 后发表回答