算法就是一个解决问题时的一个计算过程python
在算法的角度上理解程序:程序 = 数据结构 + 算法算法
数据结构:数据的储存(好比定义的列表...等等的变量)数据结构
算法:就是一个动态操做变量的过程函数
——因此其实函数也属于算法,固然函数的定义只能解决一些很是简单的问题spa
——顺而言之,其实算法的表现形式,也是以函数的形式在表现的3d
时间复杂度的引入blog
问题1很好回答,固然是第一组代码的运行时间最短,可是用什么方式来体现呢?递归
还须要引入一个生活中的实例,内存
经过这个实例,很直观的能表述出什么呢?class
很明显,咱们都知道,几毫秒<几秒<几分钟<几小时<几天/几星期/几个月<几年
因此咱们能够类比此实例,用一个能分清大小的式子来评估算法的运行效率:
O(1)< O(logn)<O(n)<O(nlogn)<O(n²)<O(n²logn)<O(n³)
而这个式子表达的是什么意思呢?以下说明:
好比刚刚最初的print代码:
其中O表示的就是大概的一个,同生活案例中的几,而括号中的内容则表示了此程序的规模
而什么又算做一个规模呢?下例:
类比以前所讲内容,咱们能够很直观的获得如上图的结果,可是!这个结果是错误的!
经过这样的答案咱们也不难看出规模指的其实就是相同量级的程序,图中3所代指的规模
并无上升到等同于n的规模,而n的规模也并无上升到n²的规模,因此用一个大概值来表示
其中O的涵义也反映了这个时间复杂度的断定标准,即一个大概的值
而logn有又什么涵义呢?下面仍然用一组实例说明:
可见,当算法过程出现折半的时候,复杂度的式子中会出现logn。
综上所说:如何简单快速的判断算法的复杂度
1.肯定问题规模——>n
2.循环减半过程——>logn
3.k层关于n的循环——>n^k
这三点适用于绝大多数简单的状况,复杂状况则须要根据算法执行过程判断
其表达方式与时间复杂度彻底同样,
对于空间换时间的理解:
——代码宁愿占用更多的内存,也要让它能实现的更快【硬件的问题都是小问题(不是对于我)】
递归有两个特色:一是调用自身,二是结束条件
因此根据这两个条件咱们先行对下面几个函数进行一下判断:
有上图可知,func3和func4为递归正确调用的方法,可是打印输出的内容确不相同,咱们用图来表示一下其运行过程,
首先是func3
执行过程如图,外层大框表示函数的调用,里面小框为print过程,而后反复如此,因此呢,咱们看到的打印结果,以x=4
为例:顺序为,4,3,2,1
而func4,运行以下图:
执行过程如图,外层大框表示函数的调用,里面小框为print过程,而后反复如此,这些与func3运行一直,惟一不一样的就是打印
代码的位置不一样,因此呢根据 如箭头的运行程序打印的结果是:1,2,3
上面两个函数的方法其实就是递归描述的一种思惟方式,那么递归思想又是从何 而来的呢?
实际上是根据这样一则故事而来,也被称之为汉诺塔问题,咱们以3个圆盘为例解析一下此问题,
那么若是是N个圆盘呢?其实咱们能够根据上图总结出必定的规律,其实整个过程主要就分为了三步,
将第N个盘子看作一部分,前N-1个盘子看作一部分,整个过程其实就是,默认三根木棍分别由A、B、C表示
首先将前N-1个盘子,由A通过C移动到B,
而后将第N个盘子,由A移动到C,
最后在前前N-1个盘子,由B通过A移动到C,这样就完成了整个过程,这也引入了咱们python算法中的汉诺塔算法:
def hanoi(n,a,b,c):
# n表示n个盘子
# a,b,c则表示了三根木棍
if n>0:
hanoi(n-1,a,c,b) # 将前n-1由a通过c移动到b
print('moving from %s to %s'%(a,c)) # 将n由a移动到c
hanoi(n-1,b,a,c) # 将前n-1有b通过a移动到c
hanoi(3,"A","B","C")
由此咱们获得了汉诺塔移动次数的递推式,
也就是两个n-1次的移动,加上1次移动,n-1次是前n-1个圆盘的,1次是最大圆盘的