算法基本概念
算法(Algorithm)是对解题方案准确而完整的描述,是解决问题的清晰指令,代表着用系统的方法描述解决问题的策略机制。
引子—>算法设计步骤
求任意两个非负整数最大公约数
问题分析
主要考虑两种算法来进行问题求解
- 穷举法
- 欧几里得算法
算法策略/建立计算模型
设a>b>0,求a,b最大公约数
- 穷举法
{ r = m i n { a , b } 初 始 化 ( a m o d r ) a n d ( b m o d r ) = = 0 满 足 则 r 为 最 大 公 约 数 r = r − 1 循 环 \left\{ \begin{array}{lr} r=min\{a,b\} & 初始化\\ (a\; mod\; r)\; and\; (b\; mod\; r) == 0 & 满足则r为最大公约数\\ r = r- 1 &循环 \end{array} \right. ⎩⎨⎧r=min{a,b}(amodr)and(bmodr)==0r=r−1初始化满足则r为最大公约数循环 - 欧几里得算法
{ r = a m o d b g c d ( a , b ) = g c d ( b , r ) r ≠ 0 g c d ( a , b ) = b r = 0 \left\{ \begin{array}{lr} r=a\; mod\;b & \\ gcd(a,b) = gcd(b,r) & r\not=0\\ gcd(a,b) = b & r = 0 \end{array} \right. ⎩⎨⎧r=amodbgcd(a,b)=gcd(b,r)gcd(a,b)=br=0r=0
gcd(a,b)表示a,b最大公约数
注:关于欧几里得方式的证明(即为证明gcd(a,b)==gcd(b,r)):
解: 设gcd(a,b) = d 且a ÷ \div ÷b = m ⋯ \cdots ⋯r
则有 d|a,d|b(“|”表示整除符号),且a = b × \times ×m + r (m ∈ \in ∈ N + N_{+} N+)
∴ \therefore ∴ d|(b × \times ×m + r)
又 ∵ \because ∵ d|b 则 d|(b × \times ×m)
∴ \therefore ∴ d|r
∴ \therefore ∴ gcd(a,b) == gcd(b,r)
老师大概是这么证明的,个人感觉还是有所欠缺,仅仅证明了d也是b,r的约数,并没有证明是最大公约数啊?
所以,加入下述证明过程(接d|r):
设 b = n 1 n_1 n1 × \times × d,r = n 2 n_2 n2 × \times × d
只要证明gcd( n 1 n_1 n1, n 2 n_2 n2) = 1 即可证明 gcd(b,r) = d
所以a = (m × \times × n 1 n_1 n1 + n 2 n_2 n2) × \times × d
下面利用反证法
若 gcd( n 1 n_1 n1, n 2 n_2 n2) = k >1
则 n 1 n_1 n1 = k × \times × n 1 n_1 n1’ , n 2 n_2 n2 = k × \times × n 2 n_2 n2’
则 a = (m × \times × n 1 n_1 n1’ + n 2 n_2 n2') × \times × k × \times ×d,b = n 2 n_2 n2' × \times ×k × \times ×d
a,b最大公约数为k × \times ×d大于d,与gcd(a,b) = d矛盾。
所以k = 1,gcd( n 1 n_1 n1, n 2 n_2 n2) = 1
从而完整证明 gcd(a,b)==gcd(b,r)。
算法设计与描述
输入:a,b
∈
\in
∈ Z
输出:a,b最大公约数
穷举法
step1:令r = min{a,b}
step2:判断是否 a mod r == 0 并且 b mod r == 0 若是转step4,否则转step3
step3:r = r - 1,转step2
step4:输出r,即为a,b最大公约数
欧几里得算法
step1:a,b = b,a(若a<b)
step2: 令 r = a mod b
step3:判断r是否为0,为0转step5,否则转step4
step4:a = b,b = r
step5:输出b,即为所求
算法分析
b = min{a,b},规定函数f(b)为循环次数
穷举法
f
(
b
)
=
∑
i
=
1
b
p
i
×
i
p
i
为
循
环
i
次
的
概
率
f(b) = \sum_{i=1}^{b}p_i\times i \quad p_i为循环i次的概率
f(b)=i=1∑bpi×ipi为循环i次的概率
若
p
i
p_i
pi =
1
b
\frac{1}{b}
b1,则有
f
f
f(
b
b
b) =
b
+
1
2
\frac{b+1}{2}
2b+1
欧几里得法
直接求f(b)难以求得,此时借助斐波那契额数列进行求解,利用渐进法。
需要引入数列
u
u
u 如下
{
u
0
=
a
,
u
1
=
b
,
u
k
=
g
c
b
(
u
k
−
2
,
u
k
−
1
)
u
n
+
1
=
0
\left\{ \begin{array}{lr} u_0 = a,u_1 = b, & \\ u_k = gcb(u_{k-2},u_{k-1})\\ u_{n+1} = 0 \end{array} \right.
⎩⎨⎧u0=a,u1=b,uk=gcb(uk−2,uk−1)un+1=0
显然此时
u
k
u_k
uk =
m
m
m
×
\times
×
u
k
+
1
u_{k+1}
uk+1 +
u
k
+
2
u_{k+2}
uk+2 (m>=1且m
∈
\in
∈Z),有
u
k
u_k
uk
≥
\geq
≥
u
k
+
1
u_{k+1}
uk+1 +
u
k
+
2
u_{k+2}
uk+2
此时将数列
u
u
u与长度为n的斐波那契数列
f
f
f进行比较,如下。
显然,有
u
n
u_{n}
un
≥
\geq
≥
f
1
f_1
f1=1,
u
n
−
1
u_{n-1}
un−1
≥
\geq
≥
f
2
f_2
f2 = 1,推出
b
b
b =
u
1
u_1
u1
≥
\geq
≥
f
n
f_n
fn
又已知,斐波那契数列的通项函数为
f
n
=
1
5
×
[
(
5
+
1
2
)
n
−
(
1
−
5
2
)
n
]
f_n = \frac{1}{\sqrt{5}}\times[(\frac{\sqrt{5}+1}{2})^n - (\frac{1-\sqrt{5}}{2})^n ]
fn=51×[(25+1)n−(21−5)n]
代入b,f(b)可得
b
=
1
5
×
[
(
5
+
1
2
)
f
(
b
)
−
(
1
−
5
2
)
f
(
b
)
]
b = \frac{1}{\sqrt{5}}\times[(\frac{\sqrt{5}+1}{2})^{f(b)} - (\frac{1-\sqrt{5}}{2})^{f(b)} ]
b=51×[(25+1)f(b)−(21−5)f(b)]
为计算方便,进行一个约算处理,当b足够大时(并非无穷大),(
1
−
5
2
)
f
(
b
)
\frac{1-\sqrt{5}}{2})^{f(b)}
21−5)f(b) 趋于0,忽略计算。
从而得出
f
(
b
)
=
log
1.618
(
5
×
b
)
f(b) = \log_{1.618}(\sqrt5 \times b)
f(b)=log1.618(5×b)
此时的f(b)为最多的循环次数。
显然,欧几里得法要远远优于穷举法
算法实现 && 测试&& 结果整理与文档整理
略
从而得到算法的设计的过程为
- 问题分析
- 算法策略/建立计算模型
- 算法设计与描述
- 算法分析
- 算法实现
- 测试
- 结果整理与文档整理
算法描述的方法
- 自然语言描述
- 程序流程图
- NS流程图
- 伪代码
- 程序设计语言
算法的递归与迭代
循环设计
- 设计思维
自底向上的设计 核心本质:合并
自底向下的设计 核心本质:分解 - 挖掘内在规律构建计算模型
挖掘问题内在规律,进行抽象并构建计算模型。
例子
设计算法,输出一个n
×
\times
×n的三角矩阵,如图所示。
问题分析
可将此两个矩阵做一个对比(
a
l
a_l
al为左图矩阵,
a
r
a_r
ar为右图矩阵。
a
l
a_l
al[
i
i
i][
j
j
j] =
k
k
k++,
i
i
i+
j
j
j<
n
n
n
a
r
a_r
ar[
i
i
i+
j
j
j][
j
j
j] =
a
l
a_l
al[
i
i
i][
j
j
j]
计算模型
{
k
=
1
初
始
化
i
=
i
+
j
i
≥
0
第
一
重
循
环
j
=
j
j
≥
0
第
二
重
循
环
a
[
i
]
[
j
]
=
k
+
+
赋
值
\left\{ \begin{array}{lr} k = 1 &&初始化 \\ i = i+j &i\geq 0&第一重循环\\ j = j &j\geq 0& 第二重循环\\ a[i][j] = k++ && 赋值 \end{array} \right.
⎩⎪⎪⎨⎪⎪⎧k=1i=i+jj=ja[i][j]=k++i≥0j≥0初始化第一重循环第二重循环赋值
算法设计与描述
输入:矩阵行列值n
输出:按斜行元素值为连续整数的三角矩阵
step1:输入n
step2:令i = 0,j = 0,k = 1
step3:令a[i+j][j] = k,k = k + 1
step4:j = j + 1 若 j = n - i ,则令j = 0,i = i + 1,若i<n,转step3
step5:打印出a数组。
注:没有转移说明默认执行下一条
算法分析
算法主体语句执行次数为:
f
(
n
)
=
∑
i
=
0
n
−
1
∑
j
=
0
n
−
i
−
1
1
=
n
(
n
−
1
)
2
f(n) = \sum_{i = 0}^{n-1}\sum_{j=0}^{n-i-1}1=\frac{n(n-1)}{2}
f(n)=i=0∑n−1j=0∑n−i−11=2n(n−1)
算法实现
测试&&结果整理与文档整理
略
递归设计
定义:一个过程或函数在定义中直接或间接调用自身的一种方法。
设计关键:找出递归关系(方程)和递归终止(边界)条件。递归关系就是使问题向边界条件转化的规则。
递归设计的步骤:
- 分析问题找到递归关系:找出大规模问题与小规模问题的关系,以便通过递归使问题规模变小。
- 设置终止条件控制递归:通过停止条件的设置,找出可解的最小规模问题。
- 设计函数确定数据传递方式。
例子
找出n个自然数(1,2,3,……,n)中取出r个数的所有组合。
问题分析
从n个数中取出r个数共有
C
n
C_n
Cn
r
r
r种取法。
下图所示n = 5,r = 3的情况。
计算模型
{
f
(
i
,
r
)
=
(
1
,
1
)
i
=
1
,
r
=
1
递
归
出
口
f
(
i
,
r
)
=
(
i
,
f
(
i
−
1
,
r
−
1
)
)
n
−
r
+
1
≤
i
≤
n
,
j
≤
i
递
归
函
数
\left\{ \begin{array}{lr} f(i,r) = (1,1) &i=1,r=1&递归出口 \\ f(i,r) = (i,f(i-1,r-1))& n-r+1\leq i\leq n,j\leq i &递归函数 \end{array} \right.
{f(i,r)=(1,1)f(i,r)=(i,f(i−1,r−1))i=1,r=1n−r+1≤i≤n,j≤i递归出口递归函数
算法设计与描述
算法分析
主要语句执行次数为f(n)
f
(
n
)
=
∑
i
=
n
r
C
i
−
1
r
−
1
f(n) = \sum_{i=n}^{r}C_{i-1}^{r-1}
f(n)=i=n∑rCi−1r−1
算法实现
附:迭代法算法实现
两者时间复杂度是一样的
基本数据结构
参考:张小东老师ppt