什么是时间复杂度?
我们可以简单理解为判断代码或算法运行时间的长短
示例一
我们首先用我们最熟悉的hello world来举例
1.最简单的直接打印输出
print("Hello world")
时间复杂度的表示:
O
(
1
)
O(1)
O(1)
2.使用单层for循环的Hello world 进行n次循环
for i in range(n):
print("Hello world")
时间复杂度表示:
O
(
n
)
O(n)
O(n)
3.使用双层for循环的Hello world 进行n次循环
for i in range(n):
for m in range(n):
print("Hello world")
复杂度表示:
O
(
n
2
)
O(n²)
O(n2)
4.多层for循环以此类推
我们为什么要使用时间复杂度来表示程序运行的快慢?运行一下不就可以了吗?使用时间复杂度有什么好处?
此处我们先来简单判断一下我们上面三个例子中那段代码运行时间最短!
我们把复杂度用O()的形式来表示
我们把基本操作:例如程序进行数字运算的加减乘除算作一次,代表的是单位一以表示为O(1)
示例二——尝试理解
1.进行三次输出操作
print("Hello world1!")
print("Hello world2!")
print("Hello world3!")
O ( 3 ) O(3) O(3)
2.for循环的改变,式子的拆分
for i in range(n):
print("Hello world,First Time")
for m in range(n):
print("Hello world, Second Time")
O ( n 2 + n ) O(n²+n) O(n2+n)
如果你认为对的话就掉入坑中了!
此处有坑!极易理解错误
第一个应该是O(1),我们把print相同操作看做单位一所以我们将其归类与一个单位所以就是O(1),此为正确答案!
第二个我们要清楚时间复杂度应该是一个近似概念所以我们只保留大单位,所以该复杂度表示为O(n²)
时间复杂度保留大单位
While循环的运算问题
while n>1:
print(n)
n=n//2
任取n为64
output:
64
32
16
8
4
2
一共可出现5个数(n>1),可以看出每次输出都数值都折半!
可以表示为2的六次方=64
转换为对数的形式即为
l
o
g
2
64
=
6
log_{2} 64=6
log264=6
对数O(logn)出现的情况
代码运行循环折半会出现
那么我们会有一个疑问,为什么logn不用log2n呢?
类似的还有lnn和lgn
此处是新高考人教版B版高中数学书必修二的内容
我们要使用一个换底公式来推导一下
这里用小a和小c代表底数
这里做个假设:
l
o
g
a
b
log_{a}b
logab
为常数
我们使用换底公式自然可以得出
l
o
g
a
b
=
l
o
g
c
b
l
o
g
c
a
log_{a}b=\frac{log_{c}b }{log_{c}a}
logab=logcalogcb
c为底数,所以logcA也是常数项
然后通过O的运算法则可以算出一个正的式子
O
(
l
o
g
a
b
)
=
O
(
l
o
g
c
b
)
O(log_{a}b )=O(log_{c}b )
O(logab)=O(logcb)
所以我们通过这个式子可以看出,算法的时间复杂度与不同底数只有常数的关系,而且我们时间复杂度要求的是一个大概的次数,要求近似!
所以我们就可以把底数进行忽略!简单记作logn
小结
-
时间复杂度是用来估计算法运行时间的一个式子
-
一般来说,时间复杂度高的算法比复杂度低的算法要慢【强调机器性能,问题规模相对一致情况下】
-
常见的时间复杂度【运行效率排序】
O ( 1 ) < O ( l o g n ) < 0 ( n ) < O ( n l o g n ) < O ( n 2 ) < O ( n 2 l o g n ) < O ( n 3 ) O(1)<O(logn)<0(n)<O(nlogn)<O(n²)<O(n²logn)<O(n³) O(1)<O(logn)<0(n)<O(nlogn)<O(n2)<O(n2logn)<O(n3) -
复杂的时间复杂度
O ( n ! ) , O ( 2 n ) , O ( n n ) . . . . O(n!),O(2^{n}),O(n^{n}).... O(n!),O(2n),O(nn)....
阶乘等用法后期会涉及到,敬请期待!本章主打基础时间复杂度算法!