欢迎来到本期频道!
这期介绍关于复杂度的经典例题。(关于复杂度是什么?在上一篇已讲解,有需要的小伙伴可以看看哦!) 让我们一起来看看以下题目吧:
Ⅰ.模拟的strchr
const char * strchr ( const char * str, char ch)
{
while ( * str)
{
if ( * str== ch)
return str;
str++ ;
}
return NULL ;
}
描述:该函数是在一个字符串str中找到第一个字符ch,找到返回该地址,没找到返回NULL。
答: 首先str的长度是N,由此可以知道while循环最多执行N次, 所以该函数的时间复杂度是O(N). 由于函数在运行时没有显示申请的额外空间,所以该函数的空间复杂度是O(1).
Ⅱ.N阶乘- -递归
int fun ( int N)
{
if ( 0 == N)
{
return 1 ;
}
return N* fun ( N- 1 ) ;
}
描述:该函数用来求一定范围内的正整数阶乘 - - N!
答: 所以该函数时间复杂度是O(N);空间复杂度是O(N).
Ⅲ.冒泡排序
void bubble_ ( int * arr, size_t n)
{
int i = 0 ;
for ( i = 0 ; i < n - 1 ; i++ )
{
int flag = 1 ;
int j = 0 ;
for ( j = 0 ; j < n - 1 - i; j++ )
{
if ( arr[ j] > arr[ j + 1 ] )
{
flag = 0 ;
int t = arr[ j] ;
arr[ j] = arr[ j + 1 ] ;
arr[ j + 1 ] = t;
}
}
if ( flag)
break ;
}
}
答: N-1和N-1-i可以看成是N,因为这是主要影响时间复杂度的项, 所以该时间复杂度为O(N²). 由于该函数没有消耗额外空间,所以该函数空间复杂度O(1).
Ⅳ.二分查找
int bisect ( int * arr, int len, int x)
{
int left= 0 ;
int right= len- 1 ;
int mid= 0 ;
while ( left<= right)
{
mid= left+ ( right- left) / 2 ;
if ( arr[ mid] < x)
{
left= mid+ 1 ;
}
else if ( arr[ mid] > x)
{
right= mid- 1 ;
}
else
return mid;
}
return - 1 ;
}
描述:该函数是在一组升序数组中找到目标值,找到返回该值的下标,没找到返回-1.
答: 一般情况下,log₂N会简写成logN,故该函数的时间复杂度为O(logN). 由于该函数没有额外的空间开销,所以该函数的空间复杂度为O(1).
Ⅴ.斐波那契数列
int fib ( int N)
{
if ( N< 3 )
return 1 ;
return fib ( N- 1 ) + fib ( N- 2 ) ;
}
为了方便计算时间复杂度,可以假设每行的调用次数都是2行数减一 , 所以f(N)=2º+2¹+···2N-1 +2N . 利用错位相减法: 2×f(N)=2¹+2² +···2N +2N+1 2×f(N)-f(N)=f(N)=2N+1 -1
结合图解分析,调用fib(5)会创建4快函数空间,所以可类推调用fib(N),N>=3,将创建N-1块函数栈帧。 故该函数的空间复杂度为O(N).