算法是计算机科学的基石。是对特定问题求解步骤的一种描述,它是指令的有限序列,其中每一条指令表示一个或多个操作。
算法理论研究的是算法的设计技术和分析技术。
基本概念
5个重要特性
- 有穷性:一个算法必须总是(对任何合法的输入值)在执行又穷步之后结束,且每一步可在又穷时间内完成。
- 确定性:算法中的每一条指令必须有确切的含义,理解时不会产生二义性。并且在任何条件下,算法只有唯一的一条执行路径,即对于相同的输入只能得出相同的输出。
- 可行性:一个算法是可行的,即算法中描述的操作都可以通过已经实现的基本运算执行有限次来实现。
- 输入:一个算法有零个或多个输入,这些输入取自于某个特定的对象的集合。
- 输出:一个算法有一个或多个输出,这些输出是同输入有着某些特定关系的量。
算法设计
设计一个好的算法应考虑多个目标,包括正确性、可读性、健壮性和高效性等。
算法设计技术也叫算法设计策略。主要有:分治法、动态规划法、贪心法、回溯法、分支限界法、概率算法和近似算法等。
算法分析
通常,求解一个问题可能会有多种算法可以选择,选择的主要标准首先是算法的正确性、可靠性、简单性和易理解性,其次是算法的时间复杂度和空间复杂度要低,这是算法分析技术的主要内容。
算法的表示
- 自然语言:优点容易理解,缺点是容易出现二义性,并且算法通常很冗长。
- 流程图:优点是直观易懂,缺点是严密性不如程序设计语言,灵活性不如自然语言。
- 程序设计语言:优点是能用于计算机直接执行,缺点是抽象性差,使算法设计者拘泥于描述算法的具体细节 ,忽略了“好”算法的正确逻辑的重要性。此外,还需要算法设计者掌握程序设计语言及编程技巧。
- 伪代码:介于自然语言和程序设计语言之间的方法,它采用某一程序设计语言的基本语法,同时结合自然语言来表达。
算法分析基础
复杂度
-
时间复杂度
主要分析算法的运行时间,即算法执行所需要的基本操作数。表示算法的执行时间与数据规模之间的增长关系。时间复杂度计算方法:
-
总复杂度等于量级最大的那段代码的复杂度
计算时间复杂度时,我们通常会忽略掉公式中的常量、低阶、高阶的系数,只需要记录一个最大介的量级就可以了。
如 O ( a n 2 + b n + c ) O(an^2+bn+c) O(an2+bn+c) 忽略常量 c,低阶 n,高阶系数 a,得到 O ( n 2 ) O(n^2) O(n2)
-
只关注循环执行次数最多的一行代码(由第 1 条推出)
-
嵌套代码的复杂度等于嵌套内外代码复杂度的乘积
-
-
空间复杂度
表示算法的存储空间与数据规模之间的增长关系。
渐进符号
-
O,渐进上界
给定一个函数g(n),O(g(n)) = {f(n):存在正常数 c 和 n 0 n_0 n0,使得对所有 n ≥ n 0 , 有 0 ≤ f ( n ) ≤ c g ( n ) n \ge n_0, 有 0 \le f(n) \le cg(n) n≥n0,有0≤f(n)≤cg(n)}。
简单来说,对于函数 f(n),在 n 0 n_0 n0后我们构造的函数g(n)的正常数(c)倍总大于f(n)。
-
Ω,渐进下界
给定一个函数g(n),Ω(g(n)) = {f(n):存在正常数 c 和 n 0 n_0 n0,使得对所有 n ≥ n 0 , 有 0 ≤ c g ( n ) ≤ f ( n ) n \ge n_0, 有 0 \le cg(n) \le f(n) n≥n0,有0≤cg(n)≤f(n)}。
-
θ,渐进紧致界
给定一个函数g(n),θ(g(n)) = {f(n):存在正常数 c 1 、 c 2 c_1、c_2 c1、c2 和 n 0 n_0 n0,使得对所有 n ≥ n 0 , 有 0 ≤ c 1 g ( n ) ≤ f ( n ) ≤ c 2 g ( n ) n \ge n_0, 有 0 \le c_1g(n) \le f(n) \le c_2g(n) n≥n0,有0≤c1g(n)≤f(n)≤c2g(n)}。
即,同时满足渐进上界和渐进下界,当且仅当 f ( n ) = O ( g ( n ) ) 且 f ( n ) = Ω ( g ( n ) ) , f ( n ) = θ ( g ( n ) ) f(n) = O(g(n)) 且 f(n) = Ω(g(n)),f(n) = θ(g(n)) f(n)=O(g(n))且f(n)=Ω(g(n)),f(n)=θ(g(n)) 才成立。
例: 10 n 2 + 4 n + 2 = O ( n 2 ) 10n^2 + 4n +2 = O(n^2) 10n2+4n+2=O(n2) 成立 , 10 n 2 + 4 n + 2 = Ω ( n 2 ) 10n^2 + 4n +2 = Ω(n^2) 10n2+4n+2=Ω(n2) 成立,所以 10 n 2 + 4 n + 2 = θ ( n 2 ) 10n^2 + 4n +2 = θ(n^2) 10n2+4n+2=θ(n2)也成立。

递归式
递归算法时间复杂度分析方法:
-
主方法(主定理)
T ( n ) = a T ( n / b ) + f ( n ) T(n) = aT(n/b) + f(n) T(n)=aT(n/b)+f(n),其中 a ≥ 1 和 b > 1 为常量,f(n) 为函数,T(n) 为定义在非负整数上的递归式,那么:
- 若对于某常数 ε \varepsilon ε,有 f ( n ) = O ( n ( l o g b a ) − ε ) f(n) = O(n^{(log_ba) - \varepsilon}) f(n)=O(n(logba)−ε),则 T ( n ) = Ω ( n l o g b a ) T(n) = Ω(n^{log_ba}) T(n)=Ω(nlogba)。
- 若 f ( n ) = Θ ( n l o g b a l g k n ) f(n) = \Theta(n^{log_ba}lg^kn) f(n)=Θ(nlogbalgkn),则 T ( n ) = Θ ( n l o g b a l g k + 1 n ) T(n) = \Theta(n^{log_ba}lg^{k+1}n) T(n)=Θ(nlogbalgk+1n) 。
- 若对于某常数
ε
\varepsilon
ε,有
f
(
n
)
=
O
(
n
(
l
o
g
b
a
)
+
ε
)
f(n) = O(n^{(log_ba)+\varepsilon})
f(n)=O(n(logba)+ε),且对于常数 c < 1 与所有足够大的 n 有
a
f
(
b
/
n
)
≤
c
f
(
n
)
af(b/n) ≤ cf(n)
af(b/n)≤cf(n),则
T
(
n
)
=
Θ
(
f
(
n
)
)
T(n) = \Theta(f(n))
T(n)=Θ(f(n))。
简单来说:将函数 f(n) 和函数 n l o g b a n^{log_ba} nlogba 进行比较,如 1、3 情况两者较大的决定了递归式的解,对于 2(相等) 的情况则再乘上一个对数因子 l g n lgn lgn,即 T ( n ) = Θ ( n l o g b a l g k + 1 n ) = Θ ( f ( n ) l g k + 1 n ) T(n) = \Theta(n^{log_ba}lg^{k+1}n) = \Theta(f(n)lg^{k+1}n) T(n)=Θ(nlogbalgk+1n)=Θ(f(n)lgk+1n)。
递归式 T ( n ) = 2 T ( n / 2 ) + n l o g n T(n) = 2T(n/2) + nlogn T(n)=2T(n/2)+nlogn, 其中 a = 2,b = 2,f(n) = nlogn, n l o g b a = Θ ( n ) n^{log_ba} = \Theta(n) nlogba=Θ(n),都不满足 1、2、3 条件,不能使用主方法计算。
常考递归式时间复杂度:
| 递归式 | 时间复杂度 | 方法 |
|---|---|---|
| T ( n ) = { 1 , n = 1 T ( n − 1 ) + n , n > 1 T(n)=\begin{cases}1 &, n=1 \\ T(n-1) + n &, n>1\end{cases} T(n)={1T(n−1)+n,n=1,n>1 | O ( n 2 ) O(n^2) O(n2) | 展开法 |
| T ( n ) = { 1 , n = 1 2 T ( n / 2 ) + n , n > 1 T(n)=\begin{cases}1 &, n=1 \\ 2T(n/2) + n &, n>1\end{cases} T(n)={12T(n/2)+n,n=1,n>1 | O ( n l o g n ) O(nlogn) O(nlogn) (上界 ) | 代换法 |
| T ( n ) = { 1 , n = 1 4 T ( n / 2 ) + c n , n > 1 T(n)=\begin{cases}1 &, n=1 \\ 4T(n/2) + cn &, n>1\end{cases} T(n)={14T(n/2)+cn,n=1,n>1 | Θ ( n 2 ) \Theta(n^2) Θ(n2) | 递归树法 |
| T ( n ) = 9 T ( n / 3 ) + n T(n)=9T(n/3) + n T(n)=9T(n/3)+n | Θ ( n 2 ) \Theta(n^2) Θ(n2)) | 主定理 |
| T ( n ) = T ( 2 n / 3 ) + 1 T(n)=T(2n/3) + 1 T(n)=T(2n/3)+1 | Θ ( l g n ) \Theta(lg n) Θ(lgn) | 主定理 |
| T ( n ) = 3 T ( n / 4 ) + n l g n T(n)=3T(n/4) + nlgn T(n)=3T(n/4)+nlgn | Θ ( n l g n ) \Theta(nlg n) Θ(nlgn) | 主定理 |
算法
| 算法 | 解决问题 | 说明 |
|---|---|---|
| 分治法 | 归并排序、最大字段问题 | 用于解决容易递归定义的问题;将一个大问题分解成多个相同的小问题,原问题的解即子问题解的合并。 |
| 动态规划法 | 0-1背包、最长公共子序列、矩阵链乘 | 将复杂问题分解成小问题求解的优化技术,通过保存子问题的解来避免重复计算;用于求解具有重叠子问题和最优子结构性质的问题,获取问题最优解。 |
| 贪心算法 | 背包问题、钱币找零、多机调度,Kruskal算法【求最小生成树】、 迪杰斯特拉(Dijkstra)【求图单源点最短路径】 | 局部最优;最优子结构、贪心选择性质 |
| 回溯法 | 0-1背包、N皇后、全排列问题 | 一种试错算法,深度优先;尝试分步解决一个问题,在分不解决过程中发现错误,则取消上一步甚至是上几步,再通过其它可能的分步解答问题。 |
| 分支界限 | 广度优先搜索 |
查找算法
| 查找算法 | 时间复杂度 | 空间复杂度 | 算法 |
|---|---|---|---|
| 顺序查找 | O(1) | O(1) | - |
| 折半查找(二分查找) | O(logn) | O(1) | 分治法 |
| 哈希查找 | O(1) | O(n) | - |
| 二叉查找树 | O(logn) | O(n) | 分治法 |
| 插值查找 | O(logn) | O(1) | 分治法 |
排序算法
| 方法 | 稳定性 | 算法 | 时间复杂度 | 空间复杂度 |
|---|---|---|---|---|
直接插入排序 | 稳定 | O ( n 2 ) O(n^2) O(n2) | O ( 1 ) O(1) O(1) | |
冒泡排序 | 稳定 | O ( n 2 ) O(n^2) O(n2) | O ( 1 ) O(1) O(1) | |
简单选择排序 | 不稳定 | O ( n 2 ) O(n^2) O(n2) | O ( 1 ) O(1) O(1) | |
希尔排序 | 不稳定 | O ( n 1.3 ) O(n^{1.3}) O(n1.3) | O ( 1 ) O(1) O(1) | |
快速排序 | 不稳定 |
O
(
n
l
o
g
2
n
)
O(nlog_2n)
O(nlog2n) 若序列有序或基本有序时: O ( n 2 ) O(n^2) O(n2) | O ( n ) O(n) O(n) | |
堆排序 | 不稳定 | n l o g n nlogn nlogn | O ( 1 ) O(1) O(1) | |
归并排序 | 稳定 | 分治法 | n l o g n nlogn nlogn | O ( n ) O(n) O(n) |
基数排序 | 稳定 | O ( n ) 或 O ( ( d + k ) ∗ n ) O(n) 或 O((d+k)*n) O(n)或O((d+k)∗n) | O ( n + d ) O(n+d) O(n+d) |
本文详细阐述了算法在计算机科学中的基础概念,包括算法的五个重要特性,以及算法设计、分析技术,如分治法、动态规划等。还介绍了时间复杂度和空间复杂度的概念,以及如何通过递归式算法分析和常见查找排序算法的比较。
算法设计与分析&spm=1001.2101.3001.5002&articleId=130680246&d=1&t=3&u=b15e5238f14545bc860c79504e7db902)
1320

被折叠的 条评论
为什么被折叠?



