赞
踩
算法是计算机处理信息的本质,因为计算机程序本质上是一个算法来告诉计算机确切的步骤来执行一个指定的任务。一般地,当算法在处理信息时,会从输入设备或数据的存储地址读取数据,把结果写入输出设备或某个存储地址供以后再调用。
算法是独立存在的一种解决问题的方法和思想。
对于算法而言,实现的语言并不重要,重要的是思想。算法可以有不同的语言描述实现版本(如C描述、C++描述、Python描述等)
算法的五大特性
输入: 算法具有0个或多个输入
输出: 算法至少有1个或多个输出
有穷性: 算法在有限的步骤之后会自动结束而不会无限循环,并且每一个步骤可以在可接受的时间内完成
确定性:算法中的每一步都有确定的含义,不会出现二义性
可行性:算法的每一步都是可行的,也就是说每一步都能够执行有限的次数完成
**假设存在函数g,使得算法A处理规模为n的问题示例所用时间为T(n)=O(g(n)),则称O(g(n))为算法A的渐近时间复杂度,简称时间复杂度,记为T(n)
**对于单调的整数函数f,如果存在一个整数函数g和实常数c>0,使得对于充分大的n总有f(n)<=c*g(n),就说函数g是f的一个渐近函数(忽略常数),记为f(n)=O(g(n))。也就是说,在趋向无穷的极限意义下,函数f的增长速度受到函数g的约束,亦即函数f与函数g的特征相似。
对于算法进行特别具体的细致分析虽然很好,但在实践中的实际价值有限。对于算法的时间性质和空间性质,最重要的是其数量级和趋势,这些是分析算法效率的主要部分。而计量算法基本操作数量的规模函数中那些常量因子可以忽略不计。例如,可以认为3n2和100n2属于同一个量级,如果两个算法处理同样规模实例的代价分别为这两个函数,就认为它们的效率“差不多”,都为n2级。
基本操作,即只有常数项,认为其时间复杂度为O(1)
顺序结构,时间复杂度按加法进行计算
循环嵌套结构,时间复杂度按乘法进行计算
分支结构,时间复杂度取最大值
判断一个算法的效率时,往往只需要关注操作数量的最高次项,其它次要项和常数项可以忽略
在没有特殊说明时,我们所分析的算法的时间复杂度都是指最坏时间复杂度
注意,经常将log2n(以2为底的对数)简写成logn
所消耗的时间从小到大:
O(1) < O(logn)(二分查找法) < O(n) < O(nlogn)(排序) < O(n2) < O(n3) < O(2n) < O(n!) < O(nn)
O(1)
O(N)
O(logN)
O(M+N)(顺序结构用加法)
O(N logN)
O(N2)(循环嵌套用乘法)
空间复杂度就是算法存储空间与输入值之间的关系。
计算空间复杂度时,关注申明的变量和递归
常见的空间复杂度就是O(1)、O(N)
O(N2)用的很少
O(logN)、O(N logN)几乎用不上
O(1)<O(N)<O(N2)
若变量是不随输入的改变而增加数据个数,那么认为其空间复杂度为O(1),e.g.:这里有一个变量total,无论num怎么变化,total只有一个值,只有一个int,即4个字节。因此空间复杂度为O(1)
这里有一个变量array,是一个列表,并且列表元素的个数随着nums一直在增加。是成正比的,因此其空间复杂度为O(N)。
注意:对于递归,哪怕没有变量,空间复杂度一般也是O(N)
时间复杂度与空间复杂度只能二选一,要么用时间换空间,要么用空间换时间。工作中一般选择时间复杂度低的算法
数组:在连续的内存空间中,存储一组相同类型的元素
数组访问(access):通过索引访问,返回元素值,如:a[1]>>2
数组搜索(search):查找某个元素,返回索引号;或遍历数组,确认某个元素是否在该数组中。
说到数据结构,必不可少的有4种方法:
数组特点:适合读,不适合写
python中列表可以添加不同类型的元素,但是数组要求存储的都是同类型的,因此用列表创建数组时人为控制同类型即可。
添加元素时的a.append()操作的时间复杂度可能为O(1)或O(N)。O(1):append是直接向尾部添加元素,当原数组后面还有剩余空间时,直接添加即可。O(N):当原数组后面已经没有空间了,仍要向数组尾部添加元素的话就要重新开辟一个更大的空间,将原数组放到新空间中,向新空间中的数组尾部添加元素。
插入元素的a.insert(插入的索引号,插入的元素)。时间复杂度O(N):因为插入元素需要把所插位置后面的元素都往后移,最差的情况就是在索引0的地方插入元素,这样的话就要移动N个元素了。
访问元素,直接用索引来访问。时间复杂度O(1):因为根据数学可以直接计算出索引位置(如id为100,一个元素占用4个字节,则a[2]就是100+2*4=108),然后去取这个元素即可,不需要遍历数组
更新元素:访问元素再直接赋值即可
删除元素:
a.remove():先搜索再删除,时间复杂度为O(N)
a.pop(索引号):先访问再删除,删除以后,因为数组是连续的内存空间,所以要将后面的元素都移动一格位置。时间复杂度为O(N)
a.pop():默认删除最后一个元素,时间复杂度为O(1)
查找元素:a.index(元素值,不是索引号),返回索引号
排序:a.sort()时间复杂度O(NlogN)
单向链表也叫单链表,是链表中最简单的一种形式,它的每个节点包含两个域,一个信息域(元素域)和一个链接域。这个链接指向链表中的下一个节点,而最后一个节点的链接域则指向一个空值。
表元素域elem用来存放具体的数据。
链接域next用来存放下一个节点的位置(python中的标识)
变量p指向链表的头节点(首节点)的位置,从p出发能找到表中的任意节点。
数组特点:适合写,不适合读
python中用队列deque()来创建链表。为了方便,现在假设a是一个链表
a.append()在链表尾部添加元素
a.insert(插入的索引位置,插入的值),之前说链表的插入时间复杂度是O(1)是指单纯一个断开next指针、重新连接的操作,这里是O(N),因为包括了插入位置的查找以及断开指针重新连接的操作
访问元素与数组一样,a[2]即可访问索引为2的元素
搜索元素 a.index(某元素),返回索引
删除元素 a.remove(某元素);del a[索引号]
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。