我们评估一种算法的优劣,可以使用它的时间复杂度和空间复杂度来衡量,当然,不作特殊说明,我们一般讨论的是该算法的最坏时间复杂度和最坏空间复杂度,即分析最坏情况以估算算法的执行时间的上界。在下面,我们会详细讨论关于斐波那契数列等函数实现的各种算法的时间复杂度和空间复杂度。
时间复杂度
我们一般采用大O渐进表示法描述一个算法的时间复杂度。时间复杂度主要讨论的是算法执行的次数。
一般算法时间复杂度O(n)的表示方法:
(1)用常数1取代运行时间中的所有加法常数 ;
(2)在修改后的运行次数函数中,只保留最高阶项;
(3)如果最高阶项系数存在且不是1,则去除与这个项相乘的常数;
(4)递归算法的时间复杂度 == 递归总次数*每次递归的次数
空间复杂度 == 递归的深度(即树的高度)
//求1+2+3+4+5+....+n
//时间复杂度为: O(n)
int Sum(int N)
{
if (1 == N)
return 1;
return Sum(N - 1) + N;
}
int main()
{
int n = 0;
printf("input:\n");
scanf("%d",&n);
int ret = Sum(n);
printf("%d\n",ret);
system("pause");
return 0;
}
斐波那契数列循环算法:(*****)
//时间复杂度:O(n)
//空间复杂度:O(1)
long long Fib(long N)
{
long long first = 1;
long long second = 1;
long long ret = 0;
int i = 3;
for (; i <= N; ++i)
{
ret = first + second;
first = second;
second = ret;
}
return second;
}
int main()
{
printf("%u\n",Fib(50));
system("pause");
return 0;
}
//斐波那契数列递归算法:
//时间复杂度: O(2^n)
//空间复杂度:O(n)
long long Fib(long long N)
{
return (N < 3) ? 1 : Fib(N - 1) + Fib(N - 2);
}
int main()
{
printf("%u\n",Fib(1,1,50));
system("pause");
return 0;
}
注意:
斐波那契数列的时间复杂度为二叉树的个数;
斐波那契数列的时间复杂度为函数调用栈的次数即二叉树的深度。
//斐波那契尾递归算法:(优化)
//时间复杂度:O(n)
//空间复杂度:O(n)
long long Fib(long long first,long long second,int N)
{
if (N < 3 )
{
return 1;
}
if (N == 3)
{
return first + second;
}
return Fib(second,first+second,N-1);
}
// 二分查找
//
//时间复杂度: log2(N) == lg(N)(最差情况)
int BinarySearch(int* array, int size, int data)
{
int left = 0;
int right = size - 1;
int mid = left + ((right - left) >> 1);
while (left <= right) //表示左闭右闭区间,可以取到边界数值; 如果left<right,表示左闭右开区间
{
if (data == array[mid])
{
return mid;
}
else if (data < array[mid])
{
right = mid - 1;//右边界改变很重要
}
else
left = mid + 1;
}
return -1;
}
解释如图:
由图知,假设在最坏情况下,循环x次找到了,则x = log2 (N)
所以时间复杂度为O(log2 (N))
空间复杂度
空间复杂度:即程序中变量的个数