时间复杂度概念的核心点:
时间复杂度就是函数走了多少次。
在计算时间复杂度的时候只是考量最坏的情况。
关注式子中增长最快的表达式,忽略其他。
忽略常数。
我们需要将时间复杂度的求解放在不同的情况下:
1.简单情况,一些循环啊什么的。
2.二分算法(分治法) 二分查找算法、堆算法 ,完全二叉搜索树和满二叉搜索树。 快速排序、归并排序 log2(N)。
3.递归算法:递归的次数*每次递归里面的时间复杂度。
主要讨论一下二分运算的时间复杂度:
以二叉树为例 如下图:


对于完全二叉树或者满二叉树,如果是搜索树,那么搜索的时间复杂度就是树的高度,因为折半查找和满二叉搜索树都是加了条件判断的,每次都将范围缩小一半,使得时间复杂度控制在lgN。
所以在后面的计算中,条件判断是不会算入时间复杂度的。而时间复杂度是在所有的条件都加上了之后最差的走的次数。
Fibonacci数列的递归与非递归:

后一个数是前两个数的和。

方案一: 递归
时间复杂度: O(2^N)(這个需要画图,但是不####太清楚,可能面试官会问到怎么算的)
空间复杂度: O(N)(最多递归了N层)
long long Fibonacci2(long long n)
{
if (n == 0)
return 0;
if (n == 1)
return 1;
return Fibonacci2(n - 1) + Fibonacci2(n - 2);
}
递归存在的问题: 如果输入的数字过大,就可能会带来栈溢出。
方案二: 非递归,使用循环, 时间复杂度: o(N) 空间复杂度o(N)
long long FibonacciR1(long long n)
{
long long* Fibarr = new long long[n + 1];
Fibarr[0] = 0;
Fibarr[1] = 1;
for (long long i = 2; i <= n; i++)
{
Fibarr[i] = Fibarr[i - 1] + Fibarr[i - 2];
}
return Fibarr[n];
}
方案三:优化非递归 使用循环,时间复杂度o(N) 空间复杂度为o(1)
long long FibonacciR2(long long n)
{
long long Fibarr[3] = { 0, 1, n };
for (long long i = 2; i <= n; i++)
{
Fibarr[2] = Fibarr[0] + Fibarr[1];
Fibarr[0] = Fibarr[1];
Fibarr[1] = Fibarr[2];
}
return Fibarr[2];
}
小结:
关于空间复杂度: 实际上空间复杂度就是对象的个数,或者说开辟的空间单元的个数。(按照某一种状态中对象个数出现次数最多的情况算)
对于递归的空间复杂度,就是递归的层数*每次递归中的对象个数。
如果说這个程序里面开辟了N个元素的数组,那么空间复杂度就是N。