与正常的斐波那契数列的唯一区别是,令f(0)=f(1)=1.
一、使用递归
#include<stdio.h>
/* Using recursive calls to itself with O(k^2)*/
int fib(int k)
{
if (k == 2 || k == 1) /*f0=f1=1*/
return 1;
else
return (fib(k - 1) + fib(k - 2)); /*f(k)=f(k-1)+f(k-2),k=2,3... equal to f(k+1)=f(k)+f(k-1),k=1,2...*/
}
int main()
{
int k, i, c; /*i is, actually the k (i=1,2,3...)in f(k+1)=f(k)+f(k-1)*/
i = 1;
k = 42; /*The # of items to calculate*/
for (c = 0; c <= k; c++)
{
/*printf("f(%d) = %d\n",i-1, fib(i));*/ /* To test*/
i++;
}
printf("f(%d) = %d\n", i - 2, fib(i - 1)); /*to show the correct values*/
return 0;
}
/* f(42) = 433494437 */
基本思路就是让f(k)=f(k-1)+f(k-2),k=2,3...然后递归求解。
当然这种方法会带来两个问题:
·1,计算的次数成平方增长,换句话说,其时间复杂度为O(n^2);
·2,由于递归过程中,大量的项会被重复计算,例如f(k)=f(k-1)+f(k-2)与f(k-1)=f(k-2)+f(k-3)中, f(k-2)便需要重复计算两次,而实际上我们只需要计算一次。
因而,在leetcode的playground中,这种方法所计算的f(42)所花时间为 1080ms
二、使用循环(迭代)
#include<stdio.h>
/*fib2 with O(k) in time complexity and O(1) in space complexity*/
int main()
{
int first, second, fib2, i, k;
i = 42; /*The # of items to calculate*/
first = 1;
second = 1;
for (k = 0; k <= i; k++)
{
if (k <= 1) /*f0=f1=1*/
fib2 = 1;
else
{
fib2 = first + second;
first = second;
second = fib2;
}
/*printf("f(%d) = %d\n", k, fib2); */ /*test*/
}
printf("f(%d) = %d\n", i, fib2);
return 0;
}
/* f(42) = 433494437 */
如果将递归的计算过程看作是从f(k)往前推,直到f(0)=f(1)=1;那么,循环则是从f(0)=f(1)=1推到f(k)
原理也很简单,基于fib2=first+second,首先求f(2)=fib2=first+second=f(0)+f(1),随后将计算而来的f(2)的值赋给second,并将f(1)的值赋给first,继而计算新的fib2...直到所需的值。此种方法相较之下,空间复杂度为O(1);时间复杂度为O(n)。
其在playground上的运行时间为:0.1ms
备注:稍微说明一下空间复杂度与时间复杂度(之前我也不太懂,hhh)
空间复杂度
一个算法在运行过程中临时占用存储空间大小的量度,记做S(n)=O(f(n))。
时间复杂度
一个关于代表算法输入值的字符串的长度的函数。时间复杂度常用O表述,不包括这个函数的低阶项和首项系数;定性描述了该算法的运行时间。
关于时间、空间复杂度不妨参考:https://www.jianshu.com/p/f4cca5ce055a
http://www.cnblogs.com/shide/p/4267331.html
https://link.jianshu.com/?t=http://blog.csdn.net/booirror/article/details/7707551/