关于算法题的一些基础笔记

时间复杂度

  在计算机科学中,算法的时间复杂度(Time complexity)是一个函数,它定性描述该算法的运行时间。这是一个代表算法输入值的字符串的长度的函数。时间复杂度常用大 O 符号表述,不包括这个函数的低阶项和首项系数。

  使用这种方式时,时间复杂度可被称为是渐近的,亦即考察输入值大小趋近无穷时的情况

  例如,如果一个算法对于任何大小为 n (必须比 n0 大)的输入,它至多需要 5n3+3n5n^3 + 3n 的时间运行完毕,那么它的渐近时间复杂度是 O(n3)O(n^3)

TIP

为了计算时间复杂度,我们通常会估计算法的操作单元数量,每个单元执行的时间都是相同的。因此,总运行时间和算法的操作单元数量最多相差一个常量系数。

空间复杂度

  既然时间复杂度不是用来计算程序具体耗时的,那么我也应该明白,空间复杂度也不是用来计算程序实际占用的空间的。

  空间复杂度是对一个算法在运行过程中临时占用存储空间大小的一个量度,同样反映的是一个趋势,我们用 S(n) 来定义。

  空间复杂度比较常用的有:O(1)O(1)O(n)O(n)O(n2)O(n^2)

范围知识

  1. c++ 1s 内可做 1e7 次计算
  2. int 范围
    • signed[int] -2147483648~+2147483648 (2e9)
    • unsigned[int] 0~4294967295 (4e9)
    • Long [int] -2147483648~+2147483648
    • Long Long int -9223372036854775808~9223372036854775807 (9e18)
    • Unsigned long long 18 446 744 073 709 551 615 (18e18)
  3. 内存范围
    • 64MB 的 内存大概可以开 64 * 2 ^ 20 / 4 = 1.6 * 10^7 个 int

TIP

编译器的优化中,只开变量不使用,不会占用内存

问题算法优先度

最大最小问题 : 二分 > dfs(暴力)> dp > 贪心

yxc 的 分享

一般 ACM 或者笔试题的时间限制是 1 秒或 2 秒。 在这种情况下,C++代码中的操作次数控制在 107∼108107∼108 为最佳。

下面给出在不同数据范围下,代码的时间复杂度和算法该如何选择:

  1. n≤30, 指数级别, dfs+剪枝,状态压缩 dp

  2. n≤100 => O(n3)O(n^3),floyd,dp,高斯消元

  3. n≤1000 => O(n2)O(n^2)O(n2logn)O(n^2logn),dp,二分,朴素版 Dijkstra、朴素版 Prim、Bellman-Ford

  4. n≤10000 => O(nn)O(n \sqrt{n}),块状链表 2 分块、莫队

  5. n≤100000 => O(nlogn)O(nlogn) => 各种 sort,线段树、树状数组、set/map、heap、拓扑排序、dijkstra+heap、prim+heap、Kruskal、spfa、求凸包、求半平面交、二分、CDQ 分治、整体二分、后缀数组、树链剖分、动态树

  6. n≤1000000n≤1000000 => O(n)O(n), 以及常数较小的 O(nlogn)O(nlogn) 算法 => 单调队列、 hash、双指针扫描、并查集,kmp、AC 自动机,常数比较小的 O(nlogn)O(nlogn) 的做法:sort、树状数组、heap、dijkstra、spfa

  7. n≤10000000 => O(n)O(n),双指针扫描、kmp、AC 自动机、线性筛素数

  8. n≤10^9 => O(n)O(\sqrt{n}),判断质数

  9. n≤10^18 => O(logn)O(logn),最大公约数,快速幂,数位 DP

  10. n≤10^1000 => O((logn)2)O((logn)^2),高精度加减乘除

  11. n≤10^100000 => O(logkloglogk)O(logk * loglogk),k 表示位数,k 表示位数,高精度加减、FFT/NTT

作者:yxc
链接:https://www.acwing.com/blog/content/32/
来源:AcWing
著题作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。