我知道我的代码现在有很多问题,但我只是想在尝试任何事情之前弄清楚这些想法。我需要一个接受整数n的方法,该整数n返回Fibonacci序列中的第n个数字。虽然通过递归正常解决它,但我必须最小化运行时,所以当它得到类似于第45个整数的东西时,它仍然会相当快地运行。另外,我不能使用类常量和全局变量。
正常的递归方式。
public static int fibonacci(int n) {
if (n <= 2) { // to indicate the first two elems in the sequence
return 1;
} else { // goes back to very first integer to calculate (n-1) and (n+1) for (n)
return fibonacci(n-1) + fibonacci(n-2);
}
}
我认为问题是这个过程中有很多冗余。我想我可以创建一个List来计算最多第n个元素,所以它只在我返回第n个元素之前运行一次。但是,在这种情况下,我无法看到如何使用递归。
如果我理解正确,标准的递归方法很慢,因为有很多重复:
fib(6)= fib(5)+ fib(4)
fib(5)= fib(4)+ fib(3)
fib(4)= fib(3)+ 1
fib(3)= 1 + 1
这是接近这个的正确方法吗?是否需要使用某种形式的容器来获得更快的输出,同时仍然是递归的?我应该使用辅助方法吗?我刚刚进入了递归编程,我很难解决这个问题,因为我已经习惯了迭代方法。感谢。
这是我有缺陷和未完成的代码:
public static int fasterFib(int n) {
ArrayList<Integer> results = new ArrayList<Integer>();
if (n <= 2) { // if
return 1;
} else if (results.size() <= n){ // If the list has fewer elems than
results.add(0, 1);
results.add(0, 1);
results.add(results.get(results.size() - 1 + results.get(results.size() - 2)));
return fasterFib(n); // not sure what to do with this yet
} else if (results.size() == n) { // base case if reached elems
return results.get(n);
}
return 0;
}
答案 0 :(得分:6)
我认为你想使用Map<Integer, Integer>
代替List
。您可能应该将该集合移出方法之外(因此它可以缓存结果) -
private static Map<Integer, Integer> results = new HashMap<>();
public static int fasterFib(int n) {
if (n == 0) {
return 0;
} else if (n <= 2) { // if
return 1;
}
if (results.get(n) != null) {
return results.get(n);
} else {
int v = fasterFib(n - 1) + fasterFib(n - 2);
results.put(n, v);
return v;
}
}
此优化称为memoization,来自维基百科文章 -
在计算中,memoization是一种优化技术,主要用于通过保留昂贵的函数调用的结果来加速计算机程序,并在再次出现相同的输入时返回缓存的结果。
答案 1 :(得分:2)
另一种方法是使用辅助方法。
static private int fibonacci(int a, int b, int n) {
if(n == 0) return a;
else return fibonacci(b, a+b, n-1);
}
static public int fibonacci(int n) {
return fibonacci(0, 1, n);
}
答案 2 :(得分:2)
您可以使用Map :: computeIfAbsent方法(自1.8起)重新使用已计算的数字。
import java.util.HashMap;
import java.util.Map;
public class Fibonacci {
private final Map<Integer, Integer> cache = new HashMap<>();
public int fib(int n) {
if (n <= 2) {
return n;
} else {
return cache.computeIfAbsent(n, (key) -> fib(n - 1) + fib(n - 2));
}
}
}
答案 3 :(得分:0)
类和私有静态HashMap怎么样?
import java.util.HashMap;
public class Fibonacci {
private static HashMap<Integer,Long> cache = new HashMap<Integer,Long>();
public Long get(Integer n) {
if ( n <= 2 ) {
return 1L;
} else if (cache.containsKey(n)) {
return cache.get(n);
} else {
Long result = get(n-1) + get(n-2);
cache.put(n, result);
System.err.println("Calculate once for " + n);
return result;
}
}
/**
* @param args
*/
public static void main(String[] args) {
Fibonacci f = new Fibonacci();
System.out.println(f.get(10));
System.out.println(f.get(15));
}
}
答案 4 :(得分:0)
public class Fibonacci {
private Map<Integer, Integer> cache = new HashMap<>();
private void addToCache(int index, int value) {
cache.put(index, value);
}
private int getFromCache(int index) {
return cache.computeIfAbsent(index, this::fibonacci);
}
public int fibonacci(int i) {
if (i == 1)
addToCache(i, 0);
else if (i == 2)
addToCache(i, 1);
else
addToCache(i, getFromCache(i - 1) + getFromCache(i - 2));
return getFromCache(i);
}
}
答案 5 :(得分:0)
您可以使用memoization(存储数组中已有的值,如果此数组的给定索引处的值不是您忽略的特定值 - >返回该值)。
代码:
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
int n = Integer.parseInt(s.nextLine());
int[] memo = new int[n+1];
for (int i = 0; i < n+1 ; i++) {
memo[i] = -1;
}
System.out.println(fib(n,memo));
}
static int fib(int n, int[] memo){
if (n<=1){
return n;
}
if(memo[n] != -1){
return memo[n];
}
memo[n] = fib(n-1,memo) + fib(n-2,memo);
return memo[n];
}
阐释:
备忘录:
-> int array (all values -1)
-> length (n+1) // easier for working on index
这可以节省大量计算时间。
答案 6 :(得分:0)
private static Map<Integer, Integer> cache = new HashMap<Integer, Integer(){
{
put(0, 0);
put(1, 1);
}
};
/**
* Smallest fibonacci sequence program using dynamic programming.
* @param n
* @return
*/
public static int fibonacci(int n){
return n < 2 ? n : cache.computeIfAbsent(n, (key) -> fibonacci( n - 1) + fibonacci(n - 2));
}
答案 7 :(得分:0)
{'key1': (((' value1', 'value2'), 'value3'), 'value4')}