概念
- 数据结构
数据结构是指一组数据的存储结构 - 算法
操作数据的方法
复杂度分析
大O复杂度表示法
复杂度分析原则
1.最大循环原则
在一个复杂度表达式中,低阶/常量/系数并不左右其增长趋势,故只需记录最大的一个量,例:T(n) = O(3n2+n+2)中,系数3低阶n和常量2可以省略不计,该表达式最终记为T(n) = O(n2)
2. 加法原则
同样遵循最大循环原则只记录最大的一个量,例:T(n) = O(n2)+O(n)中,低阶n可以省略不计,该表达式最终记为T(n) = O(n2)
3. 乘法原则
嵌套代码的复杂度等于内外层复杂度乘积,例:T(n) = O(n)*O(n),该表达式最终记为T(n) = O(n2)
时间复杂度
常见复杂度
假设每行代码执行时间相同,粗略计算得出,例:
1.O(n)
public void run(int n){
int sum = 0;
for(int i = 1;i<n;i++){
sum++;
}
}
执行时间会随着数据规模n的增大而增大
2.O(1) 常量级复杂度
public void run(int n){
int sum = 0;
for(int i = 1;i<100;i++){
sum++;
}
}
执行时间并不会随着数据规模n的增大而增大
3.O(n2)
public void run(int n){
int sum = 0;
for(int i = 1;i<n;i++){
for(int i = 1;i<n;i++){
sum++;
}
}
}
4.O(log n)
public void run(int n){
int sum = 0;
int i = 1
while(i<n){
i = i * 2;
}
}
循环第一次 21,第二次 22,第三次23,当 i = n的时候停止循环,故循环次数为log2n
5.O(n log n)
public void run(int n){
int sum = 0;
int i = 1
for(int j = 1;j<n;j++){
while(i<n){
i = i * 2;
}
}
}
复杂度曲线
可以看到日常我们经常使用的多层循环一旦遇到大数据量,就会产生严重的后果!
空间复杂度
public void run(int n){
//复杂度为O(1),因为无论数据量多大,都只开辟了一个空间
int sum = 0;
for(int i = 1;i<n;i++){
sum++;
}
//复杂度为O(n)
int[] sum = new int[n];
for(int i = 1;i<n;i++){
sum[i] = 1;//注意与赋值没有关系
}
}
最好复杂度/最坏复杂度/平均复杂度
先看一段代码
public void run(){
List list = new ArrayList<String>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
int result = -1;
for(int i = 0;i<list.size();i++){
if(3==list.get(i)){
result = list.get(i);
}
}
}
可以得出,该段代码时间复杂度为T(n) = O(n),接下来对代码进行优化,在找到要找的数字之后break,优化后的代码
public void run(){
List list = new ArrayList<String>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
int result = -1;
for(int i = 0;i<list.size();i++){
if(3==list.get(i)){
result = list.get(i);
break;
}
}
}
该代码最好的情况一次就找到并返回,最好复杂度为O(1)
该代码最坏的情况最后一次才找到,最坏复杂度为O(n+1),也就是O(n)
但一般情况下我们会使用平均复杂度去衡量,公式为:所有情况循环次数/所有情(包括要找的数不在集合中的情况),
T
(
n
)
=
1
+
2
+
3
+
.
.
.
+
n
+
n
1
+
n
=
n
2
+
3
n
2
(
1
+
n
)
T(n) =\frac{1+2+3+...+n+n}{1+n}=\frac{n^2+3n}{2(1+n)}
T(n)=1+n1+2+3+...+n+n=2(1+n)n2+3n
但这种算法没有加上概率(因为在集合中和不在集合中概率相同),公式改为
T
(
n
)
=
n
2
+
1
+
2
+
3
+
.
.
.
+
n
2
n
=
3
n
+
1
4
T(n) =\frac{n}{2}+\frac{1+2+3+...+n}{2n}=\frac{3n+1}{4}
T(n)=2n+2n1+2+3+...+n=43n+1可以看到这段代码的复杂度依旧为O(n)