斐波那契数列
我们写一个函数,输入n,求斐波那契数列的第n项。斐波那契数列的定义如下:0,1,1,2,3,5,8,13,21、、、、、 这样的一个数列。
NO1:
我们可以首先想到递归的操作方法,对于递归来说,我们就只需要找到一个递推的关系式即可“F(n)=f(n-1)+f(n-2)”,这样我们就可以写出 下面这样的代码:
long long fibonacci(unsigned int n)
{
if(n<=0)
return 0;
if(n==1)
return 1;
return fibonacci(n-1)+fibonacci(n-2)
}
对于这种方法我们不难发现他的递推过程如下:
从上图我们不难看出来我们每一次的调用都是从底层一步一步上来的,他并不具备保存的功能,有大量的重复节点,所以他的效率特别的低,当我们的n逐渐增大的增大的时候,我们的节点也会随之增大,重复的节点也会越来越多。当我们n=100的时候,将会特别的慢。
NO2:
我们可以使用循环来做,我们可以将前面的值临时保存一下,这样我们就不用一遍一遍的去计算我们重复的节点。它的时间复杂度为O(n)。
代码如下:
long long fibonacci(unsigned int n)
{
if(n==0)
return 0;
if(n==1)
return 1;
long long fibOne = 1;
long long fibTwo = 0;
long long fibN = 0;
for(unsigned i =2;i<=n;i++)
{
fibN=fibOne+fibTwo;
fibTwo=fibOne;
fibOne=fibN;
}
return fibN;
}
我们也可以使用递归去模拟循环的过程,使得不出现那么多的重复节点,如下:
int fac(int n ,int a,int b)
{
if(n <= 2) return a;
else return fac(n-1,a+b,a);
}
int fibonacci(int n)
{
int a = 1, b = 1;
return fac(n,a,b);
}
NO3:
我们还有一个时间复杂度为O(logn)算法,这种算法需要掌握一个生僻的数学公式,如下:
有了这个公式,我们只需要求得矩阵即可得到f(n)。现在我们就需要求出这个矩阵的乘方,如果从0开始的话,时间复杂度还是o(n),并不比之前的快,这时候我可以转化思想为:
这样的话,我们就可以实现O(logn)的时间复杂度了,对于这样的思想,我们可以使用递归的办法实现。
对于循环和递归,我们可以根据不同的题,选择不一样的方法。他们可以实现一样的功能,但是我们要注意的是他们的效率如何,应该使他们的效率更高。