☕目录☕
前言
思维导图
一、如何衡量一个算法的好坏
二、算法效率
三、时间复杂度
3.1 时间复杂度的概念
3.2 大O的渐进表示法
3.3 常见时间复杂度计算举例
四、空间复杂度
写在最后
现在就来回顾一下,什么是数据结构,什么是算法:
数据结构:
数据结构是计算机存储、组织数据的方式,指相互之间存在一种或多种特定关系的数据元素的集合;
就是实现项目的时候,需要在内存中把一些数据存储起来。
比如说,通讯录,需要把每个人的信息存储起来,方便以后去看。当然,有许多种储存方式,这些方式各有其优缺点,这个以后再说。
算法:
就是定义良好的计算过程,他取一个或一组的值为输入,并产生出一个或一组值作为输出;
简单来说算法就是一系列的计算步骤,用来将输入数据转化成输出结果。
常见的算法有:排序、查找、去重......
那么,现在就开始介绍 学些数据结构的 第一个前置知识点:时间复杂度和空间复杂度;
下面,正文开始......
比如说下面的斐波那契数列:
public static long Fib(int N) {
if(N<3) {
return 1;
}
return Fib(N-1) + Fib(N-2);
}
斐波那契数列的递归实现方式非常简洁,但简洁一定好吗?那该如何衡量其好与坏呢?
算法在编写成可执行程序后,运行时需要耗费时间资源和空间(内存)资源 ;
因此衡量一个算法的好坏,一般是从时间和空间两个维度来衡量的,即时间复杂度和空间复杂度;
时间复杂度主要衡量一个算法的运行快慢,而空间复杂度主要衡量一个算法运行所需要的额外空间;
在计算机发展的早期,计算机的存储容量很小。所以对空间复杂度很是在乎但是经过计算机行业的迅速发展,计算机的存储容量已经达到了很高的程度。所以我们如今已经不需要再特别关注一个算法的空间复杂度。
在计算机科学中,算法的时间复杂度是一个函数,它定量描述了该算法的运行时间。一个算法执行所耗费的时间,从理论上说,是不能算出来的,只有你把你的程序放在机器上跑起来,才能知道。但是,同一个算法,在不同电脑上运行出来所学药的时间也不一样。算法中的基本操作的执行次数,为算法的时间复杂度。
下面我们来看一看具体的例子,看看时间复杂度是多少:
public class TestDemo1 {
void func1 (int N){
int count = 0;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
count++;
}
}
for (int k = 0; k < 2*N; k++) {
count++;
}
int M = 10;
while ((M--)>0){
count++;
}
}
}
分析:
F(N)=N^2+2*N+10;
N=1,F(N)=13;
N=10,F(N)=130;
N=100;F(N)=10210;
N=1000;F(N)=1002010;......
由此可以看出,N越大,后两项对结果的影响最小;实际中我们计算时间复杂度时,我们其实 并不一定要计算精确的执行次数,而只需要大概执行次数,那么这里我们使用大O的渐进表示法。
大O符号:是用于描述函数渐进行为的数学符号。
推导大O阶方法:
另外有些算法的时间复杂度存在最好、平均和最坏情况:
最坏情况:任意输入规模的最大运行次数(上界)
平均情况:任意输入规模的期望运行次数
最好情况:任意输入规模的最小运行次数(下界)
如:在一个长度为N数组中搜索一个数据x
最好情况:1次找到
最坏情况:N次找到
平均情况:N/2次找到
在实际中一般情况关注的是算法的最坏运行情况,所以数组中搜索数据时间复杂度为:O(N)
传送门:不会有人还不知道这些常见代码的时间复杂度吧(时刻准备中......)
空间复杂度也是一个数学表达式,是对一个算法在运行过程中临时额外占用存储空间大小的量度;
空间复杂度不是程序占用了多少bytes的空间,因为这个也没太大意义,所以空间复杂度算的是变量的个数;
空间复杂度计算规则基本跟实践复杂度类似,也使用大O渐进表示法;
【注意】函数运行时所需要的栈空间(存储参数、局部变量、一些寄存器信息等)在编译期间已经确定好了,因此空间复杂度主要通过函数在运行时候显式申请的额外空间来确定。
【实例一】
使用了常数个额外空间,所以空间复杂度是:O(1)
【实例二】
动态开辟了N个空间,空间复杂度是:O(N)
【实例三】
递归调用了N次,开辟了N个栈帧,每个栈帧使用了常数个空间,空间复杂度是:O(N)
由于博主水平有限,可能会出现一些表达不清楚,或者出现一些其他的情况,
欢迎各位铁汁们指出来,和博主一起改正,
一起努力,共同进步;
好了,如果这篇博客对铁汁们有帮助的话,可以送一个免费的 赞 嘛;
当然,顺手点个关注是再好不过的了......