算法设计与分析基础(二):算法效率分析基础
怎样评价一个算法:
涉及的概念:问题的规模(大小)、基本操作、算法的最佳情况、算法的最坏情况、算法的计算复杂度、复杂度的量级、算法复杂度的下界
算法效率的评定要素:
- 应该独立于算法的描述(自然语言,框图,伪代码,高级语言)
- 应该独立于实现算法的机器
- 依赖算法中的基本操作和问题的大小
举例分析
问题:对给定的x,在n个元素互不相同的表中搜索x. 若x在表中,输出x所在的位置,否则输出-1.
算法思想:将 x 依次与每个表元进行比较
伪代码:
Algorithm:Sequential-Search(A[0..n-1], x)
// 在表L中查找关键字x, 若在表中则输出其位置, 否则返回-1
//输入:数组L[0..n-1], 关键字 x
//输出:返回第一个匹配 x 的元素下标,不在表中则返回-1
begin
i := 0;
while i<n and L[i]≠ x do
i := i+1;
3. if i<n then return i
else return -1;
end.
需要回答:输入规模是? 基本运算是? 最佳情况是? 最坏情况是?
输入规模和基本运算
-
输入规模
是指输入的数据量,也称问题的大小。
-
基本运算
算法中最基本或最关键的操作
故上面例子的输入规模为 n,基本运算为x与表元比较。
-
最优复杂度
一个算法的最优效率是指算法在最佳情况下的所花费的基本操作数。此时,与其它的输入相比,该算法运行时间最小
-
最坏复杂度
一个算法的最差效率是指算法的最坏情况下所花费的基本操作数。这时,相对于其他输入,该算法的运行时间最长。
-
平均复杂度
最佳情况与最坏情况 均反映的是算法的特殊情况,针对随机输入的情况算法平均效率(平均复杂度)则指算法在平均情况下所花费的基本操作数。
算法的计算复杂度
算法分析的原则
-
正确性
在给定有效输入后,算法经过有限时间的计算并产生正确的答案,就称算法是正确的。
-
工作量
计量工作量的标准 : 对于给定问题,该算法所执行的基本运算的次数。
-
占用空间
两种占用:
存储程序和输入数据的空间 存储中间结果或操作单元所占用空间一额外空间
影响空间的主要因素:
存储程序的空间一般是常数(和输入规模无关)
输入数据空间为输入规模O(n)
空间复杂性考虑的是额外空间的大小
如果额外空间相对于输入规模是常数,称为原地工作的算法
-
简单性
含义:算法简单,程序结构简单。
好处:容易验证正确性,便于程序调试
简单的算法效率不一定高,要在保证有一定效率的前提下力求得到简单的算法。
-
最优性
指求解某个问题的算法类中效率最高的算法
常见的算法复杂度类型
非递归算法的复杂度分析
基本步骤
- 决定算法的输入规模
- 确定算法的基本操作,(作为一规律,它总是位于算法的最内层循环中)
- 检查基本操作的执行次数是否只依赖输入规模,对应的最坏、最佳情况
- 建立一个算法基本操作执行次数的求和表达式
- 利用求和运算导出复杂度,至少确定他的量级(增长次数)
例子一
元素唯一性问题:验证给定数组中的元素是否全部唯一(互不相等)
Algorithm Unique(A[0..n-1])
//输入:数组A[0..n-1]
//输出:如果A中的元素全部唯一,返回“true”
// 否则,返回“false”.
for i←0 to n-2 do
for j←i+1 to n-1 do
if A[i]=A[j] return false
Return true
-
决定输入规模:数组元素的个数n
-
找出算法的基本操作:比较
-
检查基本操作的执行次数是否只依赖输入规模:比较的次数取决于:n
最坏情况:元素互不相同,最后两个元素是唯一 一对相同
-
建立一个算法基本操作执行的求和表达式
例子二
设计算法求一个十进制正整数在二进制表示中的二进制数字个数, 并分析算法的计算复杂度
递归算法的复杂度分析
分析递归算法效率的基本步骤
- 决定用哪个(哪些)参数作为输入规模的度量。
- 找出算法的基本操作。
- 检查一下,对于相同规模的不同输入,基本操作的执行次数是否不同。如果不同,则必须对最差效率、平均效率以及最优效率作单独研究。
- 对于算法基本操作的执行次数,建立一个递推关系以及相应的初始条件。
- 解这个递推式,或者至少确定它有解的增长次数。
例子一
汉诺塔问题. 三根柱子A, B, C, 在A上有n个半径不同的中间有孔的圆盘, 从下而上半径递减.按照下述规则将所有盘子从源盘A搬到目的C, 将B做辅助过渡:
•一次只能搬动一个盘子
•任何时候大盘子不能在小盘子上面
解题思路
n=1时, 搬动一个盘子即可;
n>1时, 分三步执行.
(1) 将n–1个盘子(最大的除外)从源移至辅柱;
(2) 将最大盘从源移至目的;
(3) 将在辅助柱上的n–1个盘子移至目的柱。
分析
1、算法可以直接给出的解答是当n=1时,需要一个单位时间的工作量,M(1)=1
2、 第一步和第三步都是将n–1个盘子从一个柱移到另一个,所以移n个盘子的问题可以分成2个移n–1个盘子的问题。
3 、其余的工作量:第二步需要一个单位时间的工作量。
M(1) = 1, (n =1)
M(n)= 2 M(n-1) +1, (n>1)
思考题
-
对给定的n个元素的集合S,设计两个算法, 不通过 排序,找出S中的第二个最小的元素。
方法一:对集合扫描两遍(当然也可以扫描一遍,同时最大和第二大元素,但花费的比较次数和扫描两遍,在最坏情况下是一样的),第一遍找出最大的元素,第二遍从剩余的元素中找出最大的元素,即整个集合的第二大元素。两遍扫描需要的比较次数为2n-3次
方法二:将集合每两个元素一组,分成n/2组,组内两个元素先进行比较,初始化两个元素,min1,min2,代表当前最小和第二小元素,然后从第一组开始,让min1和min2,依次和每组进行比较,并更新min1和min2,得到最终的整个集合的min1和min2。整个过程需要的比较次数为3*n/2次