数据结构与算法
算法概述
-
算法-前序
【1】Everybody!全场动作必须跟我整齐划一,来,我们一起来做一道题 若n1+n2+n3=1000,且n1^2+n2^2=n3^2(n1,n2,n3为自然数),求出所有n1、n2、n3可能的组合 【2】解题思路 n1 = 0 n2 = 0 n3 = 0 判断n1+n2+n3是否等于1000,之后变n3=1,n3=2,n3=3,... 然后再变n2 【3】代码实现 import time start_time = time.time() for n1 in range(0,1001): for n2 in range(0,1001): for n3 in range(0,1001): if n1 + n2 + n3 == 1000 and n1**2 + n2**2 == n3**2: print('[%d,%d,%d]' % (n1,n2,n3)) end_time = time.time() print('执行时间:%.2f' % (end_time-start_time)) 【4】算法概念 4.1) 解决问题的方法,是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令 4.2) 算法代表着用系统的方法描述解决问题的策略机制
时间复杂度概述
-
时间复杂度 - 前序
【1】各位,一万年太久,只争朝夕,来提升一下上题的效率吧!!! for n1 in range(0,1001): for n2 in range(0,1001): n3 = 1000 - n1 - n2 if n1**2 + n2**2 == n3**2: print('[%d,%d,%d]'%(n1,n2,n3)) 【2】总结与思考 : 解决同一个问题有多种算法,但是效率有区别,那么如何衡量呢? 2.1) 执行时间反应算法效率 - 绝对靠谱吗? 不是绝对靠谱: 因机器配置有高有低,不能冒然绝对去做衡量 2.2) 那如何衡量更靠谱??? 运算数量 - 执行步骤的数量 【4】时间复杂度概念 4.1) 同一个算法,由于机器配置差异,每台机器执行的总时间不同,但是执行基本运算的数量大体相同,所以把算法执行步骤的数量称为时间复杂度
-
时间复杂度 - 大O表示法前序
################################################################ 【1】计算此算法的时间复杂度 for n1 in range(0,1001): for n2 in range(0,1001): for n3 in range(0,1001): if n1 + n2 + n3 == 1000 and n1**2 + n2**2 == n3**2: print('[%d,%d,%d]' % (n1,n2,n3)) ################################################################ 【2】计算步骤 T = 1000 * 1000 * 1000 * 2 T = n * n * n * 2 T(n) = n ** 3 * 2 即时间复杂度为: T(n)=n**3 * 2 【3】时间复杂度T(n)的 大O表示法 3.1) 函数1: T(n)=k * n**3 + c 3.2) 函数2: g(n)=n**3 3.3) 特点: 在趋向无穷的极限意义下,函数T(n)的增长速度受到函数g(n)的约束,也为函数T(n)与函数g(n)的特征相似,则称 g(n) 是 T(n) 的渐近函数,大O表示法则使用渐近函数来表示 即: O(g(n)) 即: O(n^3) 即: 上述时间复杂度为 O(n^3) 【4】时间复杂度总结 4.1) 假设存在函数g,使得算法A处理规模为n的问题所用时间为T(n)=O(g(n)),则称O(g(n))为算法A的渐近时间复杂度,简称时间复杂度,记为T(n) 4.2) 对算法进行特别具体细致分析虽然好,但实践中实际价值有限。对我们来说算法的时间性质和空间性质最重要的是数量级和趋势,这些是分析算法效率的主要部分。所以忽略系数,忽略常数,比如5*n^2 和 100*n^2属于一个量级,时间复杂度为O(n^2)
-
时间复杂度分类
【1】最优时间复杂度 - 最少需要多少个步骤 【2】最坏时间复杂度 - 最多需要多少个步骤 【3】平均时间复杂度 - 平均需要多少个步骤 我们平时所说的时间复杂度,指的是最坏时间复杂度
时间复杂度 - 计算规则
-
计算原则
【1】基本操作,只有常系数,认为其时间复杂度为O(1) 顺序 - 基本步骤之间的累加 print('abc') -> O(1) print('abc') -> O(1) 【2】循环: 时间复杂度按乘法进行计算 【3】分支: 时间复杂度取最大值(哪个分支执行次数多算哪个) 【4】练习:请计算如下代码的时间复杂度 for n1 in range(0,1001): for n2 in range(0,1001): n3 = 1000 - n1 - n2 if n1**2 + n2**2 == n3**2: print('[%d,%d,%d]'%(n1,n2,n3)) T(n) = n * n * (1+1+max(1,0)) T(n) = n**2 * 3 T(n) = n**2 T(n) = O(n**2) 用大O表示法表示为 Tn = O(n^2)
-
常见时间复杂度
执行次数 时间复杂度 阶 20(20个基本步骤) O(1) 常数阶 8n+6 O(n) 线性阶 2n^2 + 4n + 2 O(n^2) 平方阶 8logn + 16 O(logn) 对数阶 4n + 3nlogn + 22 O(nlog(n)) nlog阶 2n^3 + 2n^2 + 4 O(n^3) 立方阶 2 ^ n O(2^n) 指数阶 -
O(1)
【1】O(1) print('全场动作必须跟我整齐划一') 【2】O(1) print('左边跟我一起画个龙') print('在你右边画一道彩虹') print('走起') print('左边跟我一起画彩虹') print('在你右边再画一条龙')
-
O(n)
for i in range(n): print('在胸口比划一个郭富城')
-
O(n^2)
【1】O(n^2) for i in range(n): for j in range(n): print('左边右边摇摇头') 【2】O(n^2) for i in range(n): print('两根手指就像两个窜天猴') for j in range(n): print('指向闪耀的灯球')
-
O(n^3)
for i in range(n): for j in range(n): for k in range(n): print('走你')
-
O(logn)
n = 64 while n > 1: print(n) n = n // 2 【解释】 2的6次方 等于 64,log264 = 6,所以循环减半的时间复杂度为O(log2n),即O(logn) 如果是循环减半的过程,时间复杂度为O(logn)或O(log2n)
-
O(nlogn)
for j in range(n): i = 1 while i <= n: i = i * 2
-
常见时间复杂度排序
O(1)<O(logn)<O(n)<O(nlogn)<O(n2)<O(n2logn)<O(n3)
-
练习: 写出如下的时间复杂度
O(5) --> O(1) O(2n+1) --> O(n) O(n**2+n+1) --> O(n**2) O(3n**3+1) --> O(n**3)
-
终极总结两句话
【1】时间复杂度是多少: T(n) = O(???) 【2】去掉系数、去掉常数、去掉低次幂,最终得到时间复杂度