数据结构
算法的时间复杂度
时间复杂度统计的是[计算操作数],而不是运行的绝对时间,二者呈正相关关系,还受其他其他外部因素影响。
体现的是计算操作随数据大小 NN 变化时的变化情况。假设算法运行总共需要「 11 次操作」、「 100100 次操作」,此两情况的时间复杂度都为常数级 O(1)O(1) ;需要「 NN 次操作」、「 100N100N 次操作」的时间复杂度都为 O(N)O(N) 。
时间复杂度分为三种:[最差],[平均],[最佳],分别使用O,Θ , Ω 表示
O(1)<O(logN)<O(N)<O(NlogN)<O(N2)<O(2N)<O(N!)
O(1)
package TimeComplexity_时间复杂度;
public class Demo01 {
public static void main(String[] args) {
/*
* 时间复杂度,统计计算操作数
* */
int[] ints = new int[6];
boolean flag = indexArrays(ints);
}
/*
* 计算操作数为查询数组中第一个等于7的索引值+1
* 最坏:数组.length 最佳: 第一次遍历就返回true
* 最坏:o(n)
* 最佳:Ω(1)
* 以下例题就符合以下特点
* */
public static boolean indexArrays(int[] ints) {
boolean flag=false;
for (int anInt : ints) {
if (anInt==7){
flag=true;
}
}
return flag;
}
}
int algorithm(int N) {//只有外层循环与N有关系,内层与N无关,所以时间度依然为O(n)
int count = 0;
int a = 10000;
for (int i = 0; i < N; i++) {
for (int j = 0; j < a; j++) {
count++;
}
}
return count;
}
O(n^2)
O(2^n)
多数递归算法时间复杂度为O(2^n)
public static int algorithm(int N) {//返回2^N次方
if (N <= 0) return 1;
int count_1 = algorithm(N - 1);
int count_2 = algorithm(N - 1);
return count_1 + count_2;
}
阶乘 O(n!) :
回溯法、递归
阶乘阶对应数学上常见的 “全排列” 。即给定 NN 个互不重复的元素,求其所有可能的排列方案,则方案数量为:
N \times (N - 1) \times (N - 2) \times \cdots \times 2 \times 1 = N!
N×(N−1)×(N−2)×⋯×2×1=N!
如下图与代码所示,阶乘常使用递归实现,算法原理:第一层分裂出 NN 个,第二层分裂出 N - 1N−1 个,…… ,直至到第 NN 层时终止并回溯。
对数 O(log N) :
对数阶与指数阶相反,指数阶为 “每轮分裂出两倍的情况” ,而对数阶是 “每轮排除一半的情况” 。对数阶常出现于「二分法」、「分治」等算法中,体现着 “一分为二” 或 “一分为多” 的算法思想。
线性对数 O(N log N):
两层循环相互独立,第一层和第二层时间复杂度分别为 O(log N)和 O(N),则总体时间复杂度为 O(N log N) ;
int algorithm(int N) {
int count = 0;
float i = N;
while (i > 1) {//O(log N)
i = i / 2;
for (int j = 0; j < N; j++)// O(N)
count++;
}
return count;
}
时间复杂度 | 示例题目 |
---|---|
O(1) | 剪绳子, 扑克牌中的顺子 |
O(logN) | 数值的整数次方、在排序数组中查找数字 |
O(N) | 反转链表、斐波拉契数列 |
O(NlogN) | 把数组排成最小的数、数组中的逆序对 |
O(N^2) | 二叉搜索树的后序序列、最长不含重复字符的字符串 |
O(N!) | 字符串的排列 |
2021-6-23 数据结构笔记01
参考LeetCode