3.23学堂在线python,效率和增长量级

笔记

在这一讲我们将介绍算法的复杂度,怎样衡量一个算法的复杂度,以及算法的效率,参数大小的计算需要的时间,我们的目的不是要预测算法的运行时间,而是了解算法的内在复杂度
从常量算法、到线性算法,再到多项式和指数算法
本讲结束时,你能够对算法分类,并且帮助你在设计算法时对比不同决定的时间成本

衡量算法复杂度

程序的运行时间有多长?

我希望我的代码简明,容易理解,而且我希望代码的时间复杂度尽可能低

思考一下,怎么衡量算法复杂度?我们可以给程序计时

  1. 算法取决于python程序的安装和电脑性能
  2. 还有很多时候取决于输入的好坏
使用方法排除上面1的影响来获得真正的复杂度值

好用的方法是用随机存取器来帮助我们简化这个衡量过程,衡量的不是计算机执行过程所花的时间长短,而是程序执行过程中的基本步骤执行次数来衡量算法复杂度

  • 首先我们假设各种基本操作的时间相等:算术运算、存取数据、比较大小、变量赋值

我承认这是一个比较理想的假设,但是为了算第一遍的时候方便我们不妨这么设定

很快我们就会遇到测定复杂度中难以抉择的问题

def LinearSearch(x,L):
	for i in L:
		if i==x:
			return True
	return False

这个列表搜索代码怎么定义复杂度?
如果x在列表L的最前端,当然会瞬间返回True,但是如果x不在L当中,运行时间将会大大提升
显然不能够用运行时间来定义这个本质上非常简单的程序很 “复杂”

一个好方法是 “最佳案例”,我们来看程序的输入集调整到运行时间最短会是多短?这样定义程序的复杂度
还有一个方法类似为“最糟案例”

更高端的方式是使用“期望案例”

即所有输入出现的可能性乘上分别代表的时间加起来就是一般运行时间的期望时间(数学期望)
当然有的时候输入并不是平均分布的

在本课程当中就专注于最糟案例,如此比较算法复杂度

在这里插入图片描述
在这里算法复杂度就是5n+2当然我们能够直接忽略5和2 n
在这里插入图片描述
这个二分法查找平方根的例子更为显著,在我们使用迭代的方法查找平方根的时候大约需要1,000,000,000步或者8,000,000,000步(考虑系数)走完,而递归算法只需要30步或者300步就能走完

重要的是大小,总结就是,我们最关心的是问题中的输入规模问题,并且关注最糟糕的情况

测试复杂度

我们刚才使用了随机存取器来测量程序的复杂度,利用了基本步骤来测试一个程序当中在两种情形下能够得到多少种可能的时间复杂度,并且用数学表达式表达出来是什么情形,现在我们要学习新的表示算法复杂度的方式
asymptotic notation 渐进表示

将运行时间表示为几个基本步骤的综合表达,如果运行时间使用乘积形式来表达,试图表达出影响最大的那个乘积因子。

计算复杂度的例题

给出下面的程序的最佳案例复杂度和最糟案例复杂度

def program1(L):
    multiples = []
    for x in L:
        for y in L:
            multiples.append(x*y)
    return multiples

最佳案例:2
因为def那行可以被认为没有复杂度,当L是空列表时,for语句也不具有复杂度,会直接跳过两段for语句,当然就只包含

multiples=[]
return multiples

两句

最糟案例:3n2+n+2
其中n来自于def中的n次赋值给L
2来自于

multiples=[]
return multiples

而3n2来自于这下面,for两个n乘起来和 x * y 一个n2 和 append一个 n2

for x in L:
        for y in L:
            multiples.append(x*y)

渐进复杂度

什么是渐进复杂度的阶数?

the idea of “asymptotic complexity”, which means we describe running time in terms of number of basic steps. We’ve described the best- and worst-case running times in terms number of basic steps for the three programs above. Now, we’d like you to give the complexity order (ie, “Big O” running time) of each of the above programs.

渐进复杂度意味着以基本步骤来衡量的运行时间,我们考虑了最佳/最糟的情况下的运行时间,现在我们想给出以上每个程序的复杂度的阶数。

给出一个例子

Remember the following rules when determining the complexity order of a function:

1. If running time is a sum of multiple terms, keep one with the largest growth rate (so n**3 + 100n**2 + 500,000 is O(n**3)).

2. If the remaining term is a product (eg 3n**2), drop any multiplicative constants (so 3n**2 is O(n**2)).

It's also good to note that if you have a function that takes a constant number of steps - regardless of the size of the input - the function is O(1), even if it takes 3,000,000 steps every time! This is because the function does not take any additional time as the input grows large.

Finally, pay attention to the fact that Programs 1, 2, and 3 were all O(n**2). This is important! Generally, a nested loop structure has O(n**2) complexity. This is not the best, as we'll discover in the next lectures in this sequence.

当运行时间是乘积加和的形式时,取最大增长率,例如
n3 + 100n2 + 500,000 是 O(n3)

当余项是乘积形式的时候,省略掉他们前面的常数系数
刚才提到的几个例子的复杂度都是O(n2)的
往往嵌套循环结构有O (n2)复杂性。这并不是最好的,在以后的课程当中会讲到

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值