一.什么是计算机科学?python
二.如何形象化的理解算法?程序员
三.什么是算法分析?算法
案例引入:编程
刚接触编程的学生常常会将本身编写的程序和别人的程序作比对,获取在比对的过程当中会发现双方编写的程序很类似但又各不相同。那么就会出现一个有趣的现象:两组程序都是用来解决同一个问题的,可是两组程序看起来又各不相同,那么哪一组程序更好呢?例以下述代码:数据结构
#方案一 def sumOfN(n): theSum = 0 for i in range(1,n+1): theSum = theSum + i return theSum print(sumOfN(10)) #方案二 def foo(tom): fred = 0 for bill in range(1,tom+1): barney = bill fred = fred + barney return fred print(foo(10))
分析:很明显上述两中问题的解决方案是不一样的。那如何断定上述两种解决方案(算法)的优劣呢?有同窗会说,观察计算两种算法使用耗费计算机资源的大小和它们的执行效率呀!可是我想说的是,一些较为复杂的算法,它耗费计算机资源的大小和执行效率咱们很难可以直观的从算法的编码上分析出来。因此咱们必须采用某种量化的方式求出不一样算法的资源耗费和执行效率的具体值来断定算法之间的优劣。问题来了,如何进行量化计算呢?方法有两种:数据结构和算法
#方法1:计算算法执行的耗时(不推荐)。 import time start_time = time.time() for a in range(0,1001): for b in range(0,1001): for c in range(0,1001): if a**2+b**2 == c**2 and a+b+c==1000: print(a,b,c) end_time = time.time() print(end_time-start_time) #执行结果为: 0 500 500 200 375 425 375 200 425 500 0 500 1221.7778379917145 #方法2:计算算法的时间复杂度(推荐) import time start_time = time.time() for a in range(0,1001): for b in range(0,1001): c = 1000 - a - b if a**2+b**2 == c**2 and a+b+c==1000: print(a,b,c) end_time = time.time() print(end_time-start_time) #执行结果为: 0 500 500 200 375 425 375 200 425 500 0 500 1.410386085510254
四.时间复杂度函数
时间复杂度:量化算法须要的操做或者执行步骤的数量。工具
咱们试图经过算法的执行时间来断定算法的优劣。可是仅仅根据执行时间断定算法优劣有些片面,由于算法是独立于计算机的。重要的是量化算法须要的操做或者步骤的数量。选择适当的基本计算单位是个复杂的问题,而且将取决于如何实现算法。对于先前的求和算法,一个比较好的基本计算单位是对执行语句进行计数。编码
在 sumOfN 中,赋值语句的计数为 1(theSum = 0) 加上 n 的值(咱们执行 theSum=theSum+i 的次数)。咱们经过函数 T 表示 T(n)=1+n。参数 n 一般称为“问题的规模”,咱们称做 “T(n) 是解决问题大小为 n 所花费的时间,即 1+n 步长”。在上面的求和函数中,使用 n 来表示问题大小是有意义的。咱们能够说,100,000 个整数和比 1000 个问题规模大。所以,所需时间也更长。咱们的目标是表示出算法的执行时间是如何相对问题规模大小而改变的。设计
计算机科学家更喜欢将这种分析技术进一步扩展。事实证实,操做步骤数量不如肯定 T(n) 最主要的部分来的重要。换句话说,当问题规模变大时,T(n) 函数某些部分的份量会超过其余部分。函数的数量级表示了随着 n 的值增长而增长最快的那些部分。
数量级一般称为大O符号,写为 O(f(n))。它表示对计算中的实际步数的近似。函数 f(n) 提供了 T(n) 最主要部分的表示方法。T(n)的最主要部分是:在上述示例中,T(n)=1+n。当 n 变大时,常数 1 对于最终结果变得愈来愈不重要。若是咱们找的是 T(n) 的近似值,咱们能够删除 1。所以T(n)中最主要的部分为n,所以f(n)=n。所以在sumOfN函数对应的算法的时间复杂度可即为O(f(n)),即为O(n)。
另一个示例,假设对于一些算法,肯定的步数是 T(n)=5n^2+27n+1005。当 n 很小时, 例如 1 或 2 ,常数 1005 彷佛是函数的主要部分。然而,随着 n 变大,n^2 这项变得愈来愈重要。事实上,当 n 真的很大时,其余两项在它们肯定最终结果中所起的做用变得不重要。当 n 变大时,为了近似 T(n),咱们能够忽略其余项,只关注 5n^2 。系数 5 也变得不重要。咱们说,T(n) 具备的数量级为 f(n)=n^2,或者 O( n^2 )。
常见的时间复杂度:O(1) < O(logn) < O(n) < O(nlogn) < O(n^2) < O(n^3) < O(2^n) < O(n!) < O(n^n)
案例分析:计算下列算法的时间复杂度
1 a=5 2 b=6 3 c=10 4 for i in range(n): 5 for j in range(n): 6 x = i * i 7 y = j * j 8 z = i * j 9 for k in range(n): 10 w = a*k + 45 11 v = b*b 12 d = 33
分析:前三行赋值语句执行操做步骤为3,5-8行的执行操做步骤为3n,结合第四行的外部循环,整个内外循环的执行步骤为3n^2。9-11行为2n,12行为1。最终得出T(n)=3+3n^2+2n+1,简化操做后T(n)=3n^2+2n+4。经过查看指数,咱们能够看到 n^2 项是最重要的,所以这个代码段是 O(n^ 2)。当 n 增大时,全部其余项以及主项上的系数均可以忽略。
五.数据结构:
对于数据(基本类型的数据(int,float,char))的组织方式就被称做为数据结构。数据结构解决的就是一组数据如何进行保存,保存形式是怎样的。
案例:须要存储一些学生的学生信息(name,score),那么这些数据应该如何组织呢?查询某一个具体学生的时间复杂度是什么呢?
组织形式1:
[{'name':'zhangsan','score':100}, {'name':'lisi','score':99} ]
组织形式2:
[('zhangsan',100), ('lisi',99) ]
组织形式3:
{'zhangsan':{'score':100}, 'lisi':{'score':99} }
三种组织形式基于查询的时间复杂度分别为:O(n),O(n),O(1)
发现:python中的字典,列表,元组自己就是已经被封装好的一种数据结构啦。使用不一样的数据结构进行数据的存储,所致使的时间复杂度是不同。所以认为算法是为了解决实际问题而设计的,数据结构是算法须要处理问题的载体。