1 1、数据结构和算法的做用 2 2、算法引入 3 3、算法的概念 4 4、算法的五大特征 5 5、执行时间反应算法效率 6 6、时间复杂度与“大O记法” 7 7、时间复杂度 8 8、时间复杂度的引入 9 9、引入表示时间复杂度的特征 10 10、大O表示法 11 11、最坏时间复杂度 12 12、时间复杂度的集中基本计算规则 13 13、常见时间复杂度
数据结构和算法在开发中是有序优化性能的时候的必备利器。算法
数据结构和算法的做用:服务器
若是没有数据结构和算法,有时候面对问题可能会没有任何思路不知道如何下手,或许大部分时间都能解决问题,但是程序的运行效率和开销没有意识,性能低下。数据结构
因此数据结构和算法是一个开发人员的必备基本功不是一朝一夕就能练成的,须要平时不断的去学习和积累。数据结构和算法
算法概念:ide
算法是计算机处理信息的本质,由于计算机程序本质上是一个算法告诉计算机确切的步骤来执行一个指定的任务,通常来讲,当一个算法在处理信息的时候,会从输入设备或者数据的存储地址读取数据,把结果写到输出设备或者某个存储地址之后再调用函数
若是a+b+c=100,而且a^2+b^2=c^2(a,b,c都是天然数),求出a、b、c可能的组合性能
解析:学习
首先想到的多是枚举法优化
用枚举法:spa
a=0
b=0
c=1
或者
a=0
b=1
c=1
等等这样来试验
代码以下:
import time start_time=time.time() for a in range(0,101): for b in range(0,101): for c in range(0,101): if a+b+c==100 and a**2+b**2==c**2: print("a,b,c:%d,%d,%d"%(a,b,c)) end_time=time.time() print("time:%s" %(end_time-start_time)) #time:0.17448711395263672 print("finish")
其实还能够进行优化:
import time start_time=time.time() for a in range(0,101): for b in range(0,101-a): c =100- a- b if a**2+b**2==c**2: print("a,b,c:%d,%d,%d"%(a,b,c)) end_time=time.time() print("time:%s" %(end_time-start_time)) #time:0.006990909576416016 print("finish")
这个优化解析:这里因为a和b不能相同,因此能够少一个循环遍历
而后两种程序时间结果对比,能够看出两个程序的效率
一、 输入:算法具备0个或者多个输入
二、 输出:算法至少有一个或者多个输出
三、 有穷形:算法在有限的步骤以后就会自动结束而不会无限循环,而且每个步骤能够在可接受的时间内完成
四、 肯定性:算法中的每一步都是有肯定含义的,不会出现二义性
五、 可行性:算法的每一步都是可行的,也就是说每一步都可以执行有限的次数完成
对于上面的同一个问题,给出了两种解决算法,在两种算法的实现中,咱们对程序执行的时间进行了测算,发现两端程序的时间相差悬殊,得出结论:实现算法的程序的执行时间能够反映出算法的效率,即算法的优劣
单靠时间之绝对可靠吗?
若是一段程序跑在不一样的机器上面,时间是不同的,所以单靠执行的时间来比较算法的优秀与否,并不必定是客观准确的!程序的运行离不开计算机环境(包括硬件和操做系统)这些客观缘由会影响程序运行的速度而且反应在程序的执行时间上。
每台机器执行的总时间不一样,可是执行基本运算数量和答题是相同的
什么是时间复杂度?
每台机器运行的总时间就是基本运行数量乘于每个基本步骤完成的时间
每台机器运行的总时间==基本运行数量×每个基本步骤完成的时间
基本运行数量的总和 就是时间复杂度
咱们把算法执行时间效率的快慢 称之为 时间复杂度
时间复杂度怎么去描述?
咱们用一个程序执行到底通过了多少个基本运算数量来描述时间复杂度
引入上面的程序:
import time start_time=time.time() for a in range(0,101): for b in range(0,101): for c in range(0,101): if a+b+c==100 and a**2+b**2==c**2: print("a,b,c:%d,%d,%d"%(a,b,c)) end_time=time.time() print("time:%s" %(end_time-start_time)) #time:0.17448711395263672 print("finish")
这里咱们让时间复杂度叫作T
上面这个程序的时间复杂度为多少?
第一次循环要作100次
第二次循环又要作100次
第三层循环也要作100次
第四层 细化要作10次,若是不细化,就是两句话
T=100*100*100*2
若是让上面的程序更改成a+b+c=200
T=200*200*200*2
若是是该为n
T=n*n*n*2
这类问题和规模n有关系T(n)
上面的时间复杂度就是
T(n)=n^3*2
咱们就把T(n)就叫作这个程序的时间复杂度
咱们能够把
T(n)=n^3*2
T(n)=n^3*10
上面的函数同一个数量级的也就是和T(n)=n^3 是同一个数量级的
好比服务器用的是T这个数量级,而不去关注是多少T,之前的mp3是M的数量级,而不去关心是多少M
也就是上面T(n)=n^3*10 的10这个系数只影响走势
T(n)=n^3*10+10
g(n)=n^3
T(n)=k* g(n)
T(n)和g(n)相差的就是常量 k,这个时候咱们就说g函数是T函数的渐进函数
详细解释:
“大O记法”:对于单调的整数函数f,若是存在一个整数函数g和实常数c>0,使得对于充分大的n总有f(n)<=c*g(n),就说函数g是f的一个渐近函数(忽略常数),记为f(n)=O(g(n))。也就是说,在趋向无穷的极限意义下,函数f的增加速度受到函数g的约束,亦即函数f与函数g的特征类似。 时间复杂度:假设存在函数g,使得算法A处理规模为n的问题示例所用时间为T(n)=O(g(n)),则称O(g(n))为算法A的渐近时间复杂度,简称时间复杂度,记为T(n)
咱们用提出来的g(n)(可以表示出时间复杂度的特征)就叫作一个时间复杂度的大O表示法
其实就是 可以表示时间复杂度特征 就表示时间复杂度的大O表示法
T(n)=O(g(n))
详细解释:
对于算法进行特别具体的细致分析虽然很好,但在实践中的实际价值有限。对于算法的时间性质和空间性质,最重要的是其数量级和趋势,这些是分析算法效率的主要部分。而计量算法基本操做数量的规模函数中那些常量因子能够忽略不计。例如,能够认为3n2和100n2属于同一个量级,若是两个算法处理一样规模实例的代价分别为这两个函数,就认为它们的效率“差很少”,都为n2级。
一、 基本操做,只有常数项,认为其时间复杂度为O(1)
二、 顺序结构,时间复杂度按加法进行计算
三、 循环结构,时间复杂度按惩罚进行计算
四、 分支结构,时间复杂度取最大值
五、 判断一个算法的效率的时候,每每只须要关心操做数量的最高次项,其余次要项和常数项能够忽略
六、 在没有特殊说明的时候咱们分析的算法的时间复杂度都是指的最坏时间复杂度
所以咱们把咱们优化的程序的时间复杂度为:
import time start_time=time.time() for a in range(0,101): for b in range(0,101-a): c =100- a- b if a**2+b**2==c**2: print("a,b,c:%d,%d,%d"%(a,b,c)) end_time=time.time() print("time:%s" %(end_time-start_time)) #time:0.006990909576416016 print("finish")
T(n)=n*n*(1+max(1,0))
=2n^2
所以这个程序的时间复杂度为O(n^2)
执行次数函数举例 |
阶 |
非正式术语 |
12 |
O(1) |
常数阶 |
2n+3 |
O(n) |
线性阶 |
3n2+2n+1 |
O(n2) |
平方阶 |
5log2n+20 |
O(logn) |
对数阶 |
2n+3nlog2n+19 |
O(nlogn) |
nlogn阶 |
6n3+2n2+3n+4 |
O(n3) |
立方阶 |
2n |
O(2n) |
指数阶 |
注意,常常将log2n(以2为底的对数)简写成logn
所消耗的时间从小到大:
O(1) < O(logn) < O(n) < O(nlogn) < O(n2) < O(n3) < O(2n) < O(n!) < O(nn)