Ni // i-th Fibonacci number
= Ni-1 + Ni-2 // by definition
= (Ni-2 + Ni-3) + Ni-2 // unwrap Ni-1
= 2*Ni-2 + Ni-3 // reduce the equation
= 2*(Ni-3 + Ni-4) + Ni-3 //unwrap Ni-2
// And so on
= 3*Ni-3 + 2*Ni-4
= 5*Ni-4 + 3*Ni-5
= 8*Ni-5 + 5*Ni-6
= Nk*Ni-k + Nk-1*Ni-k-1
现在我们编写一个递归函数,在每一步我们取k~ = I / 2。
static long N(long i)
{
if (i < 2) return 1;
long k=i/2;
return N(k) * N(i - k) + N(k - 1) * N(i - k - 1);
}
&#13;
错误在哪里?
答案 0 :(得分:4)
你得到了一个努力的递归公式:T(n)= 4T(n / 2)+ O(1)。 (无视数字变大的事实,所以O(1)甚至不成立)。由此可以清楚地看出T(n)不在O(log(n))中。取而代之的是主定理T(n)在O(n ^ 2)中。
顺便说一句,这比计算所有斐波纳契数最多为n的普通算法要慢。
答案 1 :(得分:2)
函数内部的四个N调用各自具有大约i / 2的参数。因此,总共N个调用的堆栈长度大致等于log 2 N,但是因为每个调用再生成四个,所以调用的底部“层”有4 ^ log 2 < / sub> N = O(n 2 )因此,错误是N自称四次。只有两次调用,如在传统的迭代方法中,它将是O(n)。我不知道有任何方法只使用一次调用,可能是O(log n)。
基于此公式的O(n)版本将是:
static long N(long i) {
if (i<2) {
return 1;
}
long k = i/2;
long val1;
long val2;
val1 = N(k-1);
val2 = N(k);
if (i%2==0) {
return val2*val2+val1*val1;
}
return val2*(val2+val1)+val1*val2;
}
每个函数调用2个N,使其成为O(n)。
答案 2 :(得分:2)
public class fibonacci {
public static int count=0;
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int i = scan.nextInt();
System.out.println("value of i ="+ i);
int result = fun(i);
System.out.println("final result is " +result);
}
public static int fun(int i) {
count++;
System.out.println("fun is called and count is "+count);
if(i < 2) {
System.out.println("function returned");
return 1;
}
int k = i/2;
int part1 = fun(k);
int part2 = fun(i-k);
int part3 = fun(k-1);
int part4 = fun(i-k-1);
return ((part1*part2) + (part3*part4)); /*RESULT WILL BE SAME FOR BOTH METHODS*/
//return ((fun(k)*fun(i-k))+(fun(k-1)*fun(i-k-1)));
}
}
我尝试编写java中定义的问题。我观察到的是上面代码的复杂性并不完全是O(N ^ 2)而是小于那个。但是根据惯例和标准,最坏情况复杂度是O(N ^ 2),包括一些其他因素,如计算(除法,乘法) )和比较时间分析。
上面代码的输出给了我关于函数多少次的信息 fun(int i)计算并被调用。
因此包括比较和除法,乘法运算所花费的时间,最坏情况下的时间复杂度是O(N ^ 2)而不是O(LogN)。
好的,如果我们使用Analysis of the recursive Fibonacci program技术。然后我们最终得到一个简单的等式
T(N)= 4 * T(N / 2)+ O(1)
其中O(1)是一些恒定时间。 那么让我们在这个等式上应用 Master's方法。 根据师父的方法
T(n) = aT(n/b) + f(n) where a >= 1 and b > 1
以下三种情况:
在我们的等式中 a = 4 , b = 2 &amp;的 C = 0 即可。
由于案例1 c < logba => 0 < 2
(对数基数为2且等于2)已满足
因此T(n) = O(n^2)
。
有关master算法如何工作的更多信息,请访问:Analysis of Algorithms
答案 3 :(得分:1)
你的想法是正确的,只要你不计算相同的公式,它就会在O(log n)中执行 一遍又一遍地。具有N(k)* N(i-k)的整个点是(k = i-k),因此您只需要计算一个而不是两个。但是如果你只是递归调用,那么你正在执行两次计算。
您需要的是 memoization 。也就是说,存储您已经计算过的每个值,以及 如果它再次出现,那么你可以在O(1)中得到它。
这是一个例子
const int MAX = 10000;
// memoization array
int f[MAX] = {0};
// Return nth fibonacci number using memoization
int fib(int n) {
// Base case
if (n == 0)
return 0;
if (n == 1 || n == 2)
return (f[n] = 1);
// If fib(n) is already computed
if (f[n]) return f[n];
// (n & 1) is 1 iff n is odd
int k = n/2;
// Applying your formula
f[n] = fib(k) * fib(n - k) + fib(k - 1) * fib(n - k - 1);
return f[n];
}