时间复杂度与空间复杂度的研究

  • O(n) 的时间复杂度不能令人满意(在一些对效率要求严格的场合);只用到几个局部变量的空间复杂度就是 O(1)
  • lg=log2 是一个增长十分缓慢的函数,这种执行时间增加慢于输入值增加的算法(等于的那是 O(n) )就是次线性时间(sublinear time)
  • 空间复杂度往往不是考虑问题的关键和核心,关键在于时间复杂度,因此不要吝惜变量或者数组矩阵的定义,用空间换时间;

O(m+n) 比如著名的无回溯的 KMP 字符串匹配算法, m 表示模式串的长度, n 为目标串的长度, O(m+n) 表示的是一种前后的逻辑关系(在 O(m) 的基础上 O(n) ), O(m) 构造 pnext 所用的时间复杂度, O(n) 根据 pnext 表进行实际匹配时所需的时间复杂度。

1. 循环之于时间复杂度

一段函数,程序的主体部分一般而言都是循环,比如 for 循环,while 循环,而不可能发生在赋值语句,if 条件分支语句(所谓分支的含义为,可执行可不执行);

for 循环与 while 循环的一大区别在于,for 循环的次数一般而言是比较固定的,while 循环视内部循环变量的具体更新形式,比如是线性的变化 O(n) ,还是二叉树对应的 O(logn)

2. O(1) 的时间复杂度

  • 使用下标索引一个线性数组;
  • 对于图的两种表示方法,要确定两个点之间是否有边
    • 邻接矩阵:直接索引mat[i][j]进行判断 ⇒ O(1)
    • 邻接表:则需要扫描一个顶点的出边表;
  • hash:也是直接索引的方式;

3. 图算法的时间复杂度

图算法的复杂度(时间和空间)一般都是基于基于图中顶点数 |V| 和边数 |E| 的度量。

现考虑 图的遍历 图的深度优先遍历算法(非递归)的复杂度。

  • 算法执行中入栈和出栈的次数对应于图中的边数 |E| ,总开销是 O(|E|) 时间;
  • 如果遇到一个未访问顶点时,需要将其出边表入栈,
    • 对于图的邻接矩阵表示,构造所有出边表的总耗时为 O(|V|2)
    • 对于图的邻接表表示,构造所有出边总耗时 O(|E|)

由于显然 |E|<|V|2 ,整个深度优先遍历下来,图的邻接矩阵的时间复杂度为 O(|V|2) ,而对于图的邻接表,时间复杂度为 O(max(|E|,|V|))

4. 多变量时间复杂度

涉及多个变量的时间复杂度,

  • 比如图的相关算法 ⇒ 顶点(V)和边(E)
  • 明星粉丝见面会 ⇒ 明星的数量(M),粉丝的数量(N)

5. 空间复杂度

数据结构(也包括一维二维数组)即意味着空间复杂度;

基本数据类型的定义,仅占用 O(1) 的空间复杂度,属于就地算法

  • 二叉树的中序遍历,对于一般的迭代版本而言,需要借助辅助栈
    所需空间复杂度的规模将正比于二叉树的高度;

你可能感兴趣的:(算法笔记)