算法 ( Algorithm )
一、功能: 有限时间内解决问题的一系列清晰指令
二、效率
- 空间
- 时间
三、目标
- 能够识别程序要求的功能以解决当前任务设计
- 能够高效解决此任务的数据结构与算法
- 评价该方案的效率和正确性
算法分析
运行时间 (时间复杂度)
- 运行时间会随着输入的大小如何变化
- 最好的情况: 运行时间的上限 (最少运行时间) 由最简单的输入决定 提供了所有输入的最终优化目标
- 最差的情况:运行时间的下限 (最多运行时间) 由最复杂的输入决定 提供了所有输入的保障时间
- 平均情况: 随机输入的运行时间的期望 需要建立随机输入的模型 是一种评价算法表现的方法
- 平均情况时间通常很难测定 ,我们通常情况下关注最差情况下的运行时间
可以看出,运行时间的效率从高到低的排序为:
Constant (常数的)> Logarithmic(对数的) > Linear(线性的) > N-log-N(N对数N) > Guadratic(二次方的) > Exponential(指数的) > Cubic(三次方的)
人类描述:
O(1) > O(logn) > O(n) > O(nlogn) > O(n^2) > O(n^3) > O(2^n) > O(n!) > O(n^n)
评估算法运行时间
算法 arrayMax 在最差情况下执行了 8n − 3 个基本操作。
定义:
a = 最快的基本操作所需要的运行时间
b = 最慢的基本操作所需要的运行时间
令 T (n) 为 arrayMax 的运行时间。
则应该有:
a (8n − 3) ≤ T (n) ≤ b (8n − 3)
因此,运行时间 T (n) 由两条线性函数所划定其范围
近似记法
Big - O 记法
一般习惯用 Θ (n) 记法来 渐进界定算法运行 时间的常数函数边界。有时,我们只希望这 个常数函数代表算法运行时间的上界。
尽管在最差情况下二分法搜索的运行时间为 Θ (lgn),认为在所有情况下二分法搜索的搜 索时间为 Θ (lgn) 是错误的。
二分法搜索的时间从来不会超过 Θ (lgn), 多数情况下其搜索时间都会少于Θ (lgn)
时间复杂度
一般情况下,算法中基本操作重复执行的次数是问题规模n的某个函数,用T(n)表示,若有某 个辅助函数f(n) ,使得当n趋近于无穷大时
T(n)/f(n)的极限值为不等于零的常数,则称 f(n)是T(n)的同数量级函数。 记作T(n)=O(f(n)),称O(f(n)) 为算法的渐进时间复杂度,简称时间复杂度
#一般我们根据时间复杂度来判断该算法的时间效率 #举例说明 for (n): xxxxxxx #这种为常见的O(n) for (n): for(m): xxxxxx #这种为O(n×m) #若嵌套的两条程度同级别可视为 O(n^2) for (n): xxxxxxx for (n): xxxxxxx #这种为O(n)+O(n),也为O(n)
附上Python内置方法时间复杂度的学习链接:
https://www.cnblogs.com/harvey888/p/6659061.html
三大算法概述
- 分治法
- 动态规划
- 贪婪算法
实际应用中可以按以下几个简化的步骤进行设计:
(1)分析最优解的性质,并刻画其结构特征。
(2)递归的定义最优解。
(3)以自底向上或自顶向下的记忆化方式(备忘录法)计算出最优值
(4)根据计算最优值时得到的信息,构造问题的最优解
算法实现的说明:
动态规划的主要难点在于理论上的设计,也就是上面4个步骤的确定,一旦设计完成,实现部分就会非常简单。
使用动态规划求解问题,最重要的就是确定动态规划三要素:
(1)问题的阶段 (2)每个阶段的状态
(3)从前一个阶段转化到后一个阶段之间的递推关系。
递推关系必须是从次小的问题开始到较大的问题之间的转化,从这个角度来说,动态规划往往可以用递归程序来实现,不过因为递推可以充分利用前面保存的子问题的解来减少重复计算,所以对于大规模问题来说,有递归不可比拟的优势,这也是动态规划算法的核心之处。
确定了动态规划的这三要素,整个求解过程就可以用一个最优决策表来描述,最优决策表是一个二维表,其中行表示决策的阶段,列表示问题状态,表格需要填写的数据一般对应此问题的在某个阶段某个状态下的最优值(如最短路径,最长公共子序列,最大价值等),填表的过程就是根据递推关系,从1行1列开始,以行或者列优先的顺序,依次填写表格,最后根据整个表格的数据通过简单的取舍或者运算求得问题的最优解。
f(n,m)=max{f(n-1,m), f(n-1,m-w[n])+P(n,m)}