什么是算法和数据结构?若是将最终写好运行的程序比做战场,咱们程序员即是指挥做战的将军,而咱们所写的代码即是士兵和武器。程序员
那么数据结构和算法是什么?答曰:兵法!故,数据结构和算法是一名程序开发人员的必备基本功,不是一朝一夕就能练成绝世高手的。冰冻三尺非一日之寒,须要咱们平时不断的主动去学习积累。算法
先来看一道题:若是 a+b+c=1000,且 a*a+b*b=c*c(a,b,c 为天然数),如何求出全部a、b、c可能的组合?数组
普通解法:浏览器
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*a+b*b == c*c and a+b+c == 1000: print("a=%d,b=%d,c=%d"%(a,b,c)) # 用于记录计算结束的时间 end_time = time.time() print("本次运算用时总计%f秒"%(end_time-start_time))
运行结果为:数据结构
a=0,b=500,c=500 a=200,b=375,c=425 a=375,b=200,c=425 a=500,b=0,c=500 本次运算用时总计397.615515秒
请注意运行时间是397.615515秒那么,若是本题稍微改一下,改成先来看一道题:若是 a+b+c=2000,且 a*a+b*b=c*c(a,b,c 为天然数),如何求出全部a、b、c可能的组合?这个时候他们解题思路和a+b+c=1000是同样的,无非就是将1000改成2000,而这种解决问题的思路就叫作算法,只不过算法也有好坏而已。数据结构和算法
算法是计算机处理信息的本质,由于计算机程序本质上是一个算法来告诉计算机确切的步骤来执行一个指定的任务。通常地,当算法在处理信息时,会从输入设备或数据的存储地址读取数据,把结果写入输出设备或某个存储地址供之后再调用。算法是独立存在的一种解决问题的方法和思想。对于算法而言,实现的语言并不重要,重要的是思想。算法能够有不一样的语言描述实现版本(如C描述、C++描述、Python描述等)函数
仍是针对上面的例子:若是 a+b+c=1000,且 a*a+b*b=c*c(a,b,c 为天然数),如何求出全部a、b、c可能的组合?优化解法:性能
import time # 用于记录计算开始的时间 start_time = time.time() # 注意这里是两重循环 for a in range(0,1001): for b in range(0,1001-a): c=1000-a-b if a*a+b*b == c*c: print("a=%d,b=%d,c=%d"%(a,b,c)) # 用于记录计算结束的时间 end_time = time.time() print("本次运算用时总计:%f秒"%(end_time-start_time))
运行结果为:学习
a=0,b=500,c=500 a=200,b=375,c=425 a=375,b=200,c=425 a=500,b=0,c=500 本次运算用时总计316.337260秒
一、执行时间反应算法效率优化
对于同一问题,咱们给出了两种解决算法,在两种算法的实现中,咱们对程序执行的时间进行了测算,发现两段程序执行的时间相差悬殊(397.615515秒相比于316.337260秒),由此咱们能够得出结论:实现算法程序的执行时间能够反应出算法的效率,即算法的优劣。
二、单靠时间绝对可信吗?
假设咱们将第二次尝试的算法程序运行在一台配置古老性能低下的计算机中,状况会如何?极可能运行的时间并不会比在咱们的电脑中运行算法一的397.615515秒快多少。单纯依靠运行的时间来比较算法的优劣并不必定是客观准确的!程序的运行离不开计算机环境(包括硬件和操做系统),这些客观缘由会影响程序运行的速度并反应在程序的执行时间上。那么如何才能客观的评判一个算法的优劣呢?
三、时间复杂度与“大O记法”
咱们假定计算机执行算法每个基本操做的时间是固定的一个时间单位,那么有多少个基本操做就表明会花费多少时间单位。固然对于不一样的机器环境而言,确切的单位时间是不一样的,可是对于算法进行多少个基本操做(即花费多少时间单位)在规模数量级上倒是相同的,由此能够忽略机器环境的影响而客观的反应算法的时间效率。
对于算法的时间效率,咱们能够用“大O记法”来表示。
“大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)
四、时间复杂度的基本计算规则
for a in range(0,1001): for b in range(0,1001): for c in range(0,1001): if a*a+b*b == c*c and a+b+c == 1000: print("a=%d,b=%d,c=%d"%(a,b,c))
时间复杂度:T(n) = O(n*n*n) = O(n^3)
优化后:
for a in range(0,1001): for b in range(0,1001-a): c=1000-a-b if a*a+b*b == c*c: print("a=%d,b=%d,c=%d"%(a,b,c))
时间复杂度:T(n) = O(n*n) = O(n^2), 因而可知,咱们尝试的第二种算法要比第一种算法的时间复杂度好多的。
注意:常常将log2n(以2为底的对数)简写成logn
所消耗的时间从小到大:O(1) < O(logn) < O(n) < O(nlogn) < O(n2) < O(n3) < O(2n) < O(n!) < O(n^n)