算法分析与设计
1.算法基本概念
1.1 算法的定义
定义一:算法是指解决问题的一种方法或者一个过程.
定义二:算法是由若干条指令组成的有穷序列,且满足下面五个特性:
确定性:组成算法的每条指令必须是明确的,没有歧义的.
有穷性:每条指令执行的次数是有穷的。算法在执行有限次后自动结束而不会出现无限循环,并且每个步骤在有限的时间内完成.
能行性:算法中的每条指令都必须是可执行的,即每一步通过执行有限次完成.
输入:有0个或者1个以上的输入
输出:至少有一个输出,否则算法没有意义.
注意:算法和程序的区别.程序可以不满足算法的有穷性条件成为计算过程,比如操作系统.
1.2算法的"好坏"如何衡量
“指标”:时间复杂度和空间复杂度
从问题的规模、基本运算到算法的计算量函数三个方面进行衡量。(独立于具体计算机的客观衡量标准)
问题规模:一个或多个整数,作为输入数据量的测度
基本运算:解决给定问题时占支配地位的运算。(一般一种,偶尔>=2种)
算法的计算量函数:用问题规模的某个函数来表示算法的基本运算量,该函数又称算法的时间复杂度。
1.3描述算法时间复杂度
渐进时间复杂度:当问题规模趋于极限情形时的时间复杂度。分为三种:O、Ω、Θ
三种时间复杂度的严格定义:
1.T(n)=O(f(n))—给出了算法时间复杂度的上界
若存在c>0和正整数n0≥1,使得当n≥n0时,总有T(n)≤c*f(n)
2.T(n)=Ω(f(n))–给出算法时间复杂度的下界
若存在c>0和正整数n0≥1,使得当n≥n0时,存在无穷多个n ,使得T(n)≥c*f(n)成立
3.T(n)=Θ(f(n))—给出算法时间复杂度的上下界(确界)
若存在c1,c2>0和正整数n0≥1,使得当n≥n0时,总有T(n)≤c1*f(n);且存在无穷多个n,使得T(n)≥c2 *f(n)成立,即:T(n)= O(f(n))与T(n)=Ω(f(n))都成立
最坏情况时间复杂度:所有输入中基本运算执行次数为最多的时间复杂度
平均情况时间复杂度:所有输入的算法时间复杂度的平均值
1.4如何评价算法
五个方面:
正确性:评价算法的首要因素。
健壮性:对不正确的输入也要能够应对处理。
简单性:可读性好,易调试、改进
高效性:时间、空间复杂度较小,特别是时复
最优性:证明所给算法是解决同一类问题中最好的。
2.递归与分治
2.1什么是分治法
分治法就是将一个规模为n的问题分解成k个规模较小的子问题进行求解,这些子问题相互独立且与原问题相同。递归的解这个子问题,然后将各个子问题的解合并得到原问题的解。
总体而言,分治法分为3步骤:分解、求解(递归)、合并
一个问题可以通过组合非重叠子问题的最优解来解决,被称为分治法。
2.2分治法与平衡的概念(重点)
分解原问题的规模,为了获得较好的合并代价,需要平衡子问题的规模,但不一定都需要严格等分的划分比如像快排的划分。
平衡:使子问题规模尽量接近
在使用分治法和递归时,要尽量把问题分成规模相等,或至少是规模相近的子问题以提高算法的效率
2.3分治与递归
递归与分治紧密相连;分治的计算式用递归式来表示
递归函数:函数包含对自身的调用
递归算法:算法包含对自身的调用。
递归式:(一个算法包含对自身的递归调用时,)递归算法其运行时间通常可以用递归式表示。
(网络寻找的内容:
递归是一种方法,而分治是一种思想。
2.4递归式的解法(重点)
三种解法:
代换法(难,并非首选)—只适用于解的形式很容易猜到的情形
步骤:1.猜测解的形式;2.数学归纳法证明它
实质就是数学归纳法:先对一个小的值进行假设,再推测更大值的正确性。
步骤:1.猜测解的形式;2.用数学归纳法求解出解中的常数,并证明解是正确的。
递归树方法(稍微有一点”不精准“,关注如何找到解的上界)—递归式表示算法时复时可用
树中每一个_节点表示一个子问题的代价,子问题对应某次递归函数调用,我们先将树中每层代价求和,得到每层的代价,然后将所有层代价求和得到所有层次的递归调用总代价。
画树时注意:先根据式子先画出递归树原始状态,然后根据递归式写出下面层的情况直到最后一层为T(1)为止。注意:递归树上层的都是常数c*式子(第一层从原式子末尾常量项找),最底层的是T(1)。
求解:1.求出树的深度,因为层数从0开始,所以计算时最后一层为深度减一!2.底层的节点个数为递归式的个数k^深度,注意换底公式AlogBC =ClogBA!【最后一层个数为Θ】3.求出总和从第一层加到最后一层(可以适当放大上界求解,注意使用等比数列求和公式!)4.2与3进行对比给出一个较大的值!
注意:求深度时,只关注每层变化量!
主定理方法
T(n)=aT(n/b)+f(n) 当a>=1,b>1且a和b均为常数时满足主定理要求 f(n)为渐进正函数
比较nlogba与f(n),只有当两者相等的时候,需要在结果上加上一