时间复杂度是为了去刻画大家构建的算法的运行时间,而运行时间与语句的执行次数呈现正比,但是精确化计算会给平时估量算法带来不便,所以我们一般用估测值来大概衡量算法
为了更好的估测用来大概描述算法,我们就要引入大O的渐进表示法
for (int i = 0; i < 10; i++)
{
cout << i << " ";
}
用大O渐进表示法表示就是O(1).在固定的执行次数下,所有的常量都可以被看作是相等的,因为它们对算法的整体性能没有影响。因此,在日常代码中,我们通常会忽略这些常量,而将注意力集中在算法的主要部分和关键性能因素上。
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
cout << "1";
}
}
for (int j = 0; j < n; j++)
{
cout << "1";
}
如上代码,n的最高阶项是n的平方,用大O渐进表示法表示就是O(N^2)
for (int j = 0; j < 2*n; j++)
{
cout << "1";
}
此处的时间复杂度表示为O(N),将系数2看作1
for (int j = 0; j < N; j++)
{
cout << "1";
}
for (int j = 0; j < M; j++)
{
cout << "1";
}
此处时间复杂度为O(M+N)
int Fib(int n)
{
if (n == 1 || n == 2) return 1;
if (n > 2)
return Fib(n - 1) + Fib(n - 2);
}
斐波那契数列的调用方式类似于二叉树,但到最后可以看出,因为条件限制,n等于1或2时停止,并返回值,
权当作不完全二叉树,我们以估算值来表示就是2的n次方,时间复杂度就是O(2^N)
将函数栈帧及其变量参数的构建看作O(1)是一种合理的近似处理方式,不过可能会涉及动态内存管理等复杂的操作可能会使改变时间复杂度
可以把斐波那契数列函数改一下:
int Fib(int n)
{
if (n == 1 || n == 2) return 1;
if (n > 2)
return Fib(n - 1);
}
如上函数调用,时间复杂度就是O(N)
空间复杂度是衡量临时占用空间大小的量度,可以看作除去提供的参数外,额外开辟的内存,比如内存申请,变量额外创建等.算法本身所需的空间,除去输入参数外,这可能包括为解决问题而创建的数据结构,变量和中间结果所占用的空间
算法使用的空间不因输入数据的大小而改变,为固定值,此时空间复杂度为O(1)
对于函数而言,计算空间复杂度还要额外考虑递归占用的栈空间等
还是斐波那契的栗子:
int Fib(int n)
{
if (n == 1 || n == 2) return 1;
if (n > 2)
return Fib(n - 1) + Fib(n - 2);
}
大家可以尝试一下计算一下上面代码的空间复杂度
对于递归的斐波那契函数,大家可以尝试去自己调试一下
int Fib(int n)
{
if (n == 1 || n == 2) return 1;
if (n > 2)
return Fib(n - 1) + Fib(n - 2);//在调试这段代码时,不会出现同时调用Fib(n-1)和Fib(n-2)的情况
//而是先调用Fib(n-1)然后在Fib(n-1)栈帧结束后,再调用Fib(n-2)
}