本系列文章是以笔记的方式进行记录,主要内容均来源于王争老师的《数据结构与算法之美》
时间复杂度
什么是数据结构,什么是算法
- 数据结构:数据结构就是指一组数据的存储结构
- 算法:算法就是操作数据的一组方法
数据结构是为算法服务的,算法要作用在特定的数据结构之上
什么是时间复杂度、空间复杂度
时间复杂度和空间复杂度是衡量算法代码的执行效率的指标。
常见的复杂度:
什么是时间复杂度
如代码:
int demo(int n) {
int sum = 0;
int i = 1;
for (; i <= n; ++i) {
sum = sum + i;
}
return sum;
}
假设每行代码执行的时间都一样,为 unit_time。
第 2、3 行代码分别需要 1 个 unit_time 的执行时间,第 4、5 行都运行了 n 遍,所以需要 2n*unit_time 的执行时间,所以这段代码总的执行时间就是 (2n+2)*unit_time。可以看出来,所有代码的执行时间 T(n) 与每行代码的执行次数成正比。 unit_time
我们吧unit_time和其他一些干扰项都归纳为O。 那么上面公式就简化为:
我们假设n趋向无限大,那么公司中的2就可以忽略了。 最后公式简化为:
我们再看一个例子:
int demo(int n) {
int sum = 0;
int i = 1;
int j = 1;
for (; i <= n; ++i) {
j = 1;
for (; j <= n; ++j) {
sum = sum + i * j;
}
}
}
上面这个例子试着自己考虑一下他的时间复杂度是多少?
思考时间。。。
思考时间。。。
思考时间。。。
答案公布:
第一步:unit_time
第二部:
第三部:
我们在扩充两个例子,如:
\
几种常见时间复杂度实例
- 常量阶
int i = 8;
int j = 6;
int sum = i + j;
一般情况下,只要算法中不存在循环语句、递归语句,即使有成千上万行的代码,其时间复杂度也是Ο(1)。
- 对数阶、线性对数阶
i=1;
while (i <= n) {
i = i * 2;
}
转化上面的代码为公式:
当n=1时:
当n=2时:
当n=4是:
由上面得出代码运行次数是, 那么经过对数转化:运行次数
如果上面的代码变为i = i * 3
,那么运行次数
又因为对数转化原则(如下图), 是一个常量,忽略掉,所以 ,因此,在对数阶时间复杂度的表示方法里,我们忽略对数的“底”,统一表示为
对log的换底公式不了解的同学可以参考这个
- 常规阶O(m+n)、O(m*n)
int demo(int m, int n) {
int sum_1 = 0;
int i = 1;
for (; i < m; ++i) {
sum_1 = sum_1 + i;
}
int sum_2 = 0;
int j = 1;
for (; j < n; ++j) {
sum_2 = sum_2 + j;
}
return sum_1 + sum_2;
}
从代码中可以看出,m 和 n 是表示两个数据规模。我们无法事先评估 m 和 n 谁的量级大,所以我们在表示复杂度的时候,就不能简单地利用加法法则,省略掉其中一个。所以,上面代码的时间复杂度就是 O(m+n)。
以上就是时间复杂度的笔记。下一篇我们学习空间复杂度。觉得好的同学可以关注我哦,大概每周更新一篇。
本系列其他文章:
《数据结构与算法》目录