认识复杂度、对数器、二分法
评估算法优劣的核心指标是什么?
时间复杂度(流程决定)
额外空间复杂度(流程决定)
常数项时间(实现细节决定)
首先说一下固定时间
什么是固定时间,即常数时间的操作 O(1)?
指常数操作:即加、减、乘、除、取余
提出问题1+3和31423424242+3142424242所需时间相同嘛?
答案是相同的,因为都是32位,32位同时进行加操作
指数组寻址
这里的数组是ArrayList这种数组,因为这种数组是一块连续的结构,查询某个位置的数值,可以通过偏移量来进行查询。即首位置+偏移位置
所以查询 2百万 位置的数值 和 查询 8百万 位置的数值 所需时间是相同的。
而 LinkedList是链表结构,在内存中不是连续的,是前一个结点记录后一个结点的位置,所以每次查询都要从头开始查询,查询 2 百万 和 8百万位置所需要的时间不同,没有偏移量。
时间复杂度
什么是时间复杂度?
对于同一个问题,每个人都有不同的算法求解,都有属于自己的算法流程。把算法流程列出来,在整个流程中,假设数据量为N,执行完整个流程,常数操作的数量是什么关系。
用快速排序举例
1)
1、N个数看一遍,找最小值(比较)
看N次 要进行(N-1)次比较
2、最小值放 0 位置 O(1) O(1)指常数时间的操作
进行一次交换
2)
1、N-1个数看一遍,找找最小值(比较)
看N-1次 要进行(N-2)次比较
2、最小值放 1 位置 O(1)
进行一次交换
…
在整个过程中,进行了多少次常数的操作
1)0 ~ N-1 看+比较 1次交换 N个数
2)1 ~ N-1 看+比较 1次交换 N-1个数
3)2 ~ N-1 看+比较 1次交换 N-2个数
…
很明显是等差数列
看+比 = a*N^2 + b*N +c
(a,b,c 为常数)
交换 = N
看+比的操作 和 交换操作的总和还是可以写为 a*N^2 + b*N +c
(a,b,c 为常数)
时间复杂度的定义:当把整个过程中,常数操作的数量集,写成一个表达式,这个表达式除了数据量N之外都是常数,时间复杂度只要最高阶项,低阶项不要,最高阶项的系数也不要,留下来的就是时间复杂度
对于本例子,选择排序而言,时间复杂度为O(n^2)
时间复杂度的意义: 当N趋于无穷大时,算法的优良是跟最高阶项有关。可以利用数据量和运行时间的关系,画数学图进行分析。
复习一下高数知识
什么是发散,什么是收敛?
有极限(极限不为无穷)就是收敛,没有极限(极限为无穷)就是发散
什么是时间复杂度?时间复杂度怎么估算?
常数时间的操作
确定算法流程的总操作数量与样本数量之间的表达式关系
只看表达式最高阶项的部分
何为常数时间的操作?
如果一个操作的执行时间不以具体样本量为转移,每次执行时间都是固定时间。称这样的操作为常数时间的操作。
常见的常数时间的操作
- 常见的算术运算(+、-、*、/、%等)
- 常见的位运算(>>、>>>、<<、|、&、^等)
- 赋值、比较、自增、自减操作等
- 数组寻址操作
总之,执行时间固定的操作都是常熟时间的操作
反之,执行时间不固定的操作,都不是常数时间的操作
当遇到不是常数时间的操作需要将其分解成为常数时间的操作
如何确定算法流程的总操作数量与样本数量之间的表达式关系?
1、想象该算法流程所处理的数据状况,要按照最差情况来
2、把整个流程彻底拆分为一个个基本动作,保证每个动作都是常数时间的操作
3、如果数据量为N,看看基本动作的数量和N是什么关系
如何确定算法流程的时间复杂度?
当完成了表达式的建立,只要把最高阶项留下即可。低阶项都去掉,高阶项的系数也去掉。
记为:O(忽略掉系数的高阶项)