我需要一些帮助,我正在为Universiy的Programming II课程编写一个程序。问题是要求使用递归计算Fibonacci序列。必须将计算出的斐波纳契数存储在一个数组中,以阻止不必要的重复计算并减少计算时间。
我设法让程序在没有数组和记忆的情况下工作,现在我正在尝试实现它并且我被卡住了。我不确定如何构建它。我用谷歌搜索并略读了一些书籍,但没有找到太多帮助我解决如何实施解决方案。
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);
}
}
以上是不正确的,我的fib方法的结束是主要问题。我不知道如何让它以递归的方式将数字添加到数组的正确部分。
答案 0 :(得分:20)
您需要区分字典中已计算的数字和未计算的数字,而您目前不会:始终重新计算数字。
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;
}
答案 1 :(得分:7)
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;
}
与上述大多数解决方案类似,但使用的是地图。
答案 2 :(得分:4)
使用Memoization打印首个n
斐波纳契数字的程序。
int[] dictionary;
// Get Fibonacci with Memoization
public int getFibWithMem(int n) {
if (dictionary == null) {
dictionary = new int[n];
}
if (dictionary[n - 1] == 0) {
if (n <= 2) {
dictionary[n - 1] = n - 1;
} else {
dictionary[n - 1] = getFibWithMem(n - 1) + getFibWithMem(n - 2);
}
}
return dictionary[n - 1];
}
public void printFibonacci()
{
for (int curr : dictionary) {
System.out.print("F[" + i++ + "]:" + curr + ", ");
}
}
答案 3 :(得分:3)
我相信你忘了在字典里查找一些内容。
更改
else
return dictionary[n] = fibonacci(n-1) + fibonacci(n-2);
到
else {
if (dictionary[n] > 0)
return dictionary[n];
return dictionary[n] = fibonacci(n - 1) + fibonacci(n - 2);
}
它工作正常(我自己测试过:):
答案 4 :(得分:2)
这是我对递归斐波那契记忆的实现。使用BigInteger和ArrayList可以计算出第100个甚至更长的项。我尝试了第1000个术语,结果在几毫秒内返回,这里是代码:
private static List<BigInteger> dict = new ArrayList<BigInteger>();
public static void printFebonachiRecursion (int num){
if (num==1){
printFebonachiRecursion(num-1);
System.out.printf("Term %d: %d%n",num,1);
dict.add(BigInteger.ONE);
}
else if (num==0){
System.out.printf("Term %d: %d%n",num,0);
dict.add(BigInteger.ZERO);
}
else {
printFebonachiRecursion(num-1);
dict.add(dict.get(num-2).add(dict.get(num-1)));
System.out.printf("Term %d: %d%n",num,dict.get(num));
}
}
输出示例
printFebonachiRecursion(100);
Term 0: 0
Term 1: 1
Term 2: 1
Term 3: 2
...
Term 98: 135301852344706746049
Term 99: 218922995834555169026
Term 100: 354224848179261915075
答案 5 :(得分:1)
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;
}
答案 6 :(得分:1)
这是使用静态值数组来处理递归fibonacci()方法的memoization的另一种方法 -
public static long fibArray[]=new long[50];\\Keep it as large as you need
public static long fibonacci(long n){
long fibValue=0;
if(n==0 ){
return 0;
}else if(n==1){
return 1;
}else if(fibArray[(int)n]!=0){
return fibArray[(int)n];
}
else{
fibValue=fibonacci(n-1)+fibonacci(n-2);
fibArray[(int) n]=fibValue;
return fibValue;
}
}
请注意,此方法使用全局(类级别)静态数组fibArray []。要查看整个代码并附上说明,您还可以看到以下内容 - http://www.javabrahman.com/gen-java-programs/recursive-fibonacci-in-java-with-memoization/
答案 7 :(得分:1)
这是一个利用 memoization 概念的完全成熟的课程:
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;
}
}
请注意
memoizedMap.put(0, 0);
memoizedMap.put(1, 1);
用于消除以下检查的必要性
if (n == 0) return 0;
if (n == 1) return 1;
在每次递归函数调用时。
答案 8 :(得分:0)
import java.util.HashMap;
import java.util.Map;
public class FibonacciSequence {
public static int fibonacci(int n, Map<Integer, Integer> memo) {
if (n < 2) {
return n;
}
if (!memo.containsKey(n)) {
memo.put(n, fibonacci(n - 1, memo) + fibonacci(n - 2, memo));
}
return memo.get(n);
}
public static int fibonacci(int n, int[] memo) {
if (n < 2) {
return n;
}
if (memo[n - 1] != 0) {
return memo[n - 1];
}
return memo[n - 1] = fibonacci(n - 1, memo) + fibonacci(n - 2, memo);
}
public static void main(String[] s) {
int n = 10;
System.out.println("f(n) = " + fibonacci(n, new HashMap<Integer, Integer>()));
System.out.println("f(n) = " + fibonacci(n, new int[n]));
}
}
答案 9 :(得分:0)
可能太老了,但这是我的快速解决方案
class Recursion {
func fibonacci(_ input: Int) {
var dictioner: [Int: Int] = [:]
dictioner[0] = 0
dictioner[1] = 1
print(fibonacciCal(input, dictioner: &dictioner))
}
func fibonacciCal(_ input: Int, dictioner: inout [Int: Int]) -> Int {
if let va = dictioner[input]{
return va
} else {
let firstPart = fibonacciCal(input-1, dictioner: &dictioner)
let secondPart = fibonacciCal(input-2, dictioner: &dictioner)
if dictioner[input] == nil {
dictioner[input] = firstPart+secondPart
}
return firstPart+secondPart
}
}
}
// 0,1,1,2,3,5,8
class TestRecursion {
func testRecursion () {
let t = Recursion()
t.fibonacci(3)
}
}
答案 10 :(得分:0)
public class FiboSeries {
// first two terms of Fibonacci
int x1 = 0;
int x2 = 1;
long xn; // nth number in Fibo series
long[] array; // an array for implementing memoization
// print the Nth number of Fibonacci - logic is f(n) = f(n-1) + f(n-2)
long fibo(int n) {
// initialize the array having n elements if it does not exist already
if (array == null) {
array = new long[n + 1];
}
// Fetch the memoized value from the array instead of recursion
// for instance, fibo(3) will be calculated just once and stored inside this
// array for next call
if (array[n] != 0)
{
xn = array[n];
return xn;
}
// value of fibo(1)
if (n == 1) {
xn = x1;
}
// value of fibo(2)
if (n == 2) {
xn = x2;
}
// value of Fibo(n) using non linear recursion
if (n > 2) {
xn = fibo(n - 1) + fibo(n - 2);
}
// before returning the value - store it at nth position of an array
// However, before saving the value into array, check if the position is already
//full or not
if (array[n] == 0) {
array[n] = xn;
}
return xn;
}
public static void main(String[] args) {
FiboSeries f = new FiboSeries();
int n = 50;
long number = f.fibo(n);
System.out.println(number);
}
}
答案 11 :(得分:0)
这是使用备忘录的非常快速的方法。 首先,我初始化缓存字典。
var cache = [Int:Int]()
然后创建我的斐波那契数字生成器。由于它是一个递归函数,因此从理论上讲,对该函数的每次调用都会再次计算整个斐波那契数列,直到请求的数量为止。这就是为什么我们使用缓存来加快递归功能的原因:
func fibonacci(_ number: Int) -> Int {
// if the value is in the dictionary I just return it
if let value = cache[number] { return value }
// Otherwise I calculate it recursively.
// Every recursion will check the cache again,
// this is why memoisation is faster!
let newValue = number < 2 ? number : fibonacci(number - 1) + fibonacci(number - 2)
cache[number] = newValue
return newValue
}
我可以将序列保存在这样的数组中:
var numbers = Array(0..<10).map(fibonacci) //[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
或循环使用该功能。
答案 12 :(得分:-1)
#include <stdio.h>
long int A[100]={1,1};
long int fib(int n){
if (A[n])
{
return A[n];
}
else
{
return A[n]=fib(n-1)+fib(n-2);
}
}
int main(){
printf("%ld",fib(30));
}
答案 13 :(得分:-1)
这是我的实现。
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];
}
答案 14 :(得分:-1)
记忆,但采用O(log n)方法。 参考http://www.maths.surrey.ac.uk/hosted-sites/R.Knott/Fibonacci/fibFormula.html
private static HashMap<Integer, Integer> lookup = new HashMap<>();
private static int fib(int n){
if(lookup.containsKey(n))
return lookup.get(n);
else{
if(n <= 1)
lookup.put(n, n);
else{
int k = (n & 1) == 1? (n+1)/2 : n/2;
if((n&1) == 1)
lookup.put(n, fib(k) * fib(k) + fib(k-1) * fib(k-1));
else
lookup.put(n, (2 * fib(k-1) + fib(k))*fib(k));
}
return lookup.get(n);
}
}
答案 15 :(得分:-1)
使用系统; 使用 System.Collections.Generic;
命名空间斐波那契 { 公共类斐波那契数列 {
static void Main(string[] args)
{
int n;
Dictionary<int, long> dict = new Dictionary<int, long>();
Console.WriteLine("ENTER NUMBER::");
n = Convert.ToInt32(Console.ReadLine());
for (int j = 0; j <= n; j++)
{
Console.WriteLine(Fib(j, dict));
}
}
public static long Fib(int n, Dictionary<int, long> dict)
{
if (n <= 1)
return n;
if (dict.ContainsKey(n))
return dict[n];
var value = Fib(n - 1,dict) + Fib(n - 2,dict);
dict[n] = value;
return value;
}
}
}