学习时间复杂度和空间复杂度

评判算法的标准

  • 时效高和存储低
  • 「时效」是指时间效率,也就是算法的执行时间
  • 「存储」是指算法在执行的时候需要的存储空间

时间复杂度(一般是最坏情况下的时间复杂度)

根据数量级,描述时间复杂度,一般用「大 O」表示,记做 O(f(n)),n为数据的规模

常见数量级函数
1

当 n 增大时,数量级函数增长幅度排名

O(1) < O(logn) < O(n) < O(nlogn) < O(n^2) < O(n^3) < O(2^n)
2

1.常数函数

n = 100  # 1 次
sum  = (1 + n) *n / 2 # 1 次
print(sum) # 1 次

上面的算法程序的时间复杂度就是 O(1)

无论 n 为多少,代码就是 运行 3 次。这种与数据的规模大小 n 无关,执行时间恒定的算法我们就叫它具有 O(1) 的时间复杂度。

2.对数函数

cnt = 1
while cnt < n:
   cnt *= 2 # O(1)

上面的算法程序的时间复杂度就是 O(logn)

上述的代码可以解释成 cnt 乘以多少个 2 以后才能大于等于 n,我们假设个数是 x,也就是求 2^x = n,即 x = log2n,所以这个循环的时间复杂度就是 O(logn)。

3.综合

a = 1
b = 2
c = 3

for i in range(n):
   for j in range(n):
       x = i * i
       y = j * j
       z = i * j

for k in range(n):
   u = a * k + b
   v = c * c

d = 4

上面程序的时间复杂度就是 O(n^2)

可以分成 4 部分:
第 1 部分是 a,b,c 这 3 个赋值语句,执行次数也就是 3 次;
第二部分是 3n^2,因为是循环结构,里面有 x,y,z 这 3 个赋值语句,每个语句执行了 n^2 次;
第 3 部分是 2n,因为里面是 2 个赋值语句,每条语句被执行了 n 次;
第 4 部分是常数 1,只有 d 这么 1 条赋值语句。
所以我们得到的 T(n) = 3+3n^2 +2n+1 = 3n^2+2n+4,看到指数项,我们自然的发现是 n^2 做主导,当 n 增大时,后面两项可以忽略掉,所以这个代码片段的数量级就是 O(n^2)

空间复杂度

算法所耗费的存储空间,计算公式计作:S(n) = O(f(n))。其中 n 也为数据的规模,f(n) 在这里指的是 n 所占存储空间的函数。

一般情况下,我们的程序在机器上运行时,刨去需要存储程序本身的输入数据等之外,还需要存储对数据操作的「存储单元」。如果输入数据所占空间和算法无关,只取决于问题本身,那么只需要分析算法在实现过程中所占的「辅助单元」即可。如果所需的辅助单元是个常数,那么空间复杂度就是 O(1)。

空间复杂度其实在这里更多的是说一下这个概念,因为当今硬件的存储量级比较大,一般不会为了稍微减少一点儿空间复杂度而大动干戈,更多的是去想怎么优化算法的时间复杂度。所以我们在日常写代码的时候就衍生出了用「空间换时间」的做法,并且成为常态。比如我们在求解斐波那契数列数列的时候我们可以直接用公式去递归求,用哪个求哪个,同样也可以先把很多结果都算出来保存起来,然后用到哪个直接调用,这就是典型的用空间换时间的做法,但是你说这两种具体哪个好,伟大的马克思告诉我们「具体问题具体分析」。

猜你喜欢

转载自blog.csdn.net/u010828718/article/details/83142993