目录
什么是数据结构?
什么是算法?
1、算法的特性
1.1 五个特征
1.2 设计原则
1.3 评价算法的两个总要指标:时间复杂度和空间复杂度
2、时间复杂度分析
2.1 时间复杂度表示方法:大O表示法
2.2 时间复杂度如何分析
2.3 复杂度比较
2.4 时间复杂度分析
3、空间复杂度分析
就是一组能组在一起的集合对象。比如数组、链表、队列等。
就是解决问题的
有穷性、确定性、可行性、有输入、有输出
while(true){}//死循环,不是算法
正确性、可读性、健壮性(bug):写出的代码很少有bug,且系统比较稳定
高效率与低存储:内存+CPU(内存占用最小,CPU占用最小,运算速度最快)
时间复杂度:运行一个程序所花费的时间,O()表示
空间复杂度:运行程序所需要的内存(尽可能避免出现OOM(内存溢出))
O(1),O(n),O(logn),O(nlogn),O(n^2),O(2^n)
(1)找for、while、递归,而且要找循环量大的那一段
(2)有网络请求的地方(http,rpc远程调用,数据库请求)
就是测试时间:打印log,计算平均时间
O(1) < O(logn) < O(n) < O(nlogn) < O(n^2) < O(n^3)
计算时间复杂度 往往是计算比较大的 而且是不确定的数,如果已经确定了,那么就不用计算了,也是我们说的常量。
常数级O(1)
public static void main(String[] args) {
int a = 1; //1次 O(1)
for(int i = 0 ;i < 3;i++){//这里会运行几次?4次 在第4次的时候结束 跳出 i=3 (0 1 2 3)
a = a + 1; //这里运行几次? 3次 O(1)? n+1 n 1 O(3)? => O(1)
}
}
对数级O(logn)
public static void main(String[] args) {
int n = Integer.MAX_VALUE; //表示n是未知
int i = 1;
while( i <= n){
i = i * 2; //O(logn)
}
//i的值:2 4 8 16 32,=》2^0,2^1,2^2,2^3,.....2^n
//===> 2^x=n =>求出x就是我们运行的次数 => x=log2n =>计算机忽略掉常数 => x = logn =>O(logn)
//二分查找 为什么是logn的算法?
//1~100 找69这个数
//50:(1+100)/2 = 50
}
线性对数级O(nlogn)
public static void main(String[] args) {
int n = Integer.MAX_VALUE; //表示n是未知
int i = 1;
for(int j = 0 ; j < n ;j++){//O(n)
while ( i <= n){
i = i * 2;//O(logn)
}
}
}
线性级O(n)
public static void main(String[] args) {
int n = Integer.MAX_VALUE; //表示n是未知
int a = 1; //1次 O(1)
for(i = 0 ; i < n;i++){
a = a +1; //运行了多少次?O(n) n一定是一个未知的,如果n是已知6的,则是O(1)
}
}
平方级别O(n^2)
public static void main(String[] args) {
int n = Integer.MAX_VALUE; //表示n是未知
int a = 1; //1次 O(1)
for(i = 0 ; i < n;i++){ // 乘法 n次
for(int j = 0 ; j < n ;j ++){ //n次
a = a +1; //运行了多少次?O(n^2)n*(n+1)/2 => O(n^2); => (n^2+n)/2
//注意有个规律,有加减法的时候,找次数最高的那个
}
}
}
指数级O(2^n)
long aFunc(int n) { //运行多少次?
if (n <= 1) {
return 1;
} else {
return aFunc(n - 1) + aFunc(n - 2);
}
}
//运行次数T(0)=T(1)=1,同时T(n)=T(n-1)+T(n-2)+1,1是其中的加法算一次执行
//显然T(n)=T(n-1)+T(n-2)是斐波那契数列,通过归纳证明法可以证明,
//当n>=1 时,T(n)<(5/3)^n,同时n>4时T(n)>=(3/2)^n,
//所以该方法的时间复杂度可以表示为O(5/3)^n,简化后为O(2^n)
如何查找空间复杂度?
(1)找花了内存的地方。数据
(2)找开了空间的地方,比如数组、链表、缓存对象(map)、递归
总结
学了时间复杂度,那我们的目的就是要把代码写到最优,效率最高
效率有高到低:O(1) > O(logn) > O(n) >O(nlogn) >O(n^2) >O(n^3)
比如排序,冒泡算法的时间复杂度是O(n^2)=>找更优秀的排序算法:快速排序、归并排序、堆排序
优化的目标就是要往O(1)靠近
本文来源于小编的另一分享平台:算法基础 - 知乎 (zhihu.com)