算法基本概念
算法(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 = m i n { a , b } ( a m o d r ) a n d ( b m o d r ) = = 0 r = 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 = a m o d b g c d ( a , b ) = g c d ( b , r ) g c d ( a , b ) = b r = 0 r = 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 n 1 × \times × d,r = n 2 n_2 n 2 × \times × d
只要证明gcd(n 1 n_1 n 1 ,n 2 n_2 n 2 ) = 1 即可证明 gcd(b,r) = d
所以a = (m× \times × n 1 n_1 n 1 + n 2 n_2 n 2 )× \times × d
下面利用反证法
若 gcd(n 1 n_1 n 1 ,n 2 n_2 n 2 ) = k >1
则 n 1 n_1 n 1 = k × \times × n 1 n_1 n 1 ’ ,n 2 n_2 n 2 = k × \times × n 2 n_2 n 2 ’
则 a = (m× \times × n 1 n_1 n 1 ’ + n 2 n_2 n 2 ')× \times × k× \times × d,b = n 2 n_2 n 2 '× \times × k× \times × d
a,b最大公约数为k× \times × d大于d,与gcd(a,b) = d矛盾。
所以k = 1,gcd(n 1 n_1 n 1 ,n 2 n_2 n 2 ) = 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 ∑ b p i × i p i 为 循 环 i 次 的 概 率
若p i p_i p i = 1 b \frac{1}{b} b 1 ,则有f f f (b b b ) = b + 1 2 \frac{b+1}{2} 2 b + 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.
⎩ ⎨ ⎧ u 0 = a , u 1 = b , u k = g c b ( u k − 2 , u k − 1 ) u n + 1 = 0
显然此时u k u_k u k = m m m × \times × u k + 1 u_{k+1} u k + 1 + u k + 2 u_{k+2} u k + 2 (m>=1且m∈ \in ∈ Z),有u k u_k u k ≥ \geq ≥ u k + 1 u_{k+1} u k + 1 + u k + 2 u_{k+2} u k + 2
此时将数列u u u 与长度为n的斐波那契数列f f f 进行比较,如下。
显然,有u n u_{n} u n ≥ \geq ≥ f 1 f_1 f 1 =1,u n − 1 u_{n-1} u n − 1 ≥ \geq ≥ f 2 f_2 f 2 = 1,推出b b b = u 1 u_1 u 1 ≥ \geq ≥ f n f_n f n
又已知,斐波那契数列的通项函数为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 ]
f n = 5 1 × [ ( 2 5 + 1 ) n − ( 2 1 − 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 = 5 1 × [ ( 2 5 + 1 ) f ( b ) − ( 2 1 − 5 ) f ( b ) ]
为计算方便,进行一个约算处理,当b足够大时(并非无穷大),(1 − 5 2 ) f ( b ) \frac{1-\sqrt{5}}{2})^{f(b)} 2 1 − 5 ) f ( b ) 趋于0,忽略计算。
从而得出f ( b ) = log 1.618 ( 5 × b )
f(b) = \log_{1.618}(\sqrt5 \times b)
f ( b ) = log 1 . 6 1 8 ( 5 × b )
此时的f(b)为最多的循环次数。显然,欧几里得法要远远优于穷举法
算法实现 && 测试&& 结果整理与文档整理
略
从而得到算法的设计的过程 为
问题分析
算法策略/建立计算模型
算法设计与描述
算法分析
算法实现
测试
结果整理与文档整理
算法描述的方法
自然语言描述
程序流程图
NS流程图
伪代码
程序设计语言
算法的递归与迭代
循环设计
设计思维
自底向上的设计 核心本质:合并
自底向下的设计 核心本质:分解
挖掘内在规律构建计算模型
挖掘问题内在规律,进行抽象并构建计算模型。
例子
设计算法,输出一个n× \times × n的三角矩阵,如图所示。问题分析
可将此两个矩阵做一个对比(a l a_l a l 为左图矩阵,a r a_r a r 为右图矩阵。a l a_l a l [i i i ][j j j ] = i i i × \times × n n n +j j j a r a_r a r [i i i +j j j ][j j j ] = a l a_l a l [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 = 1 i = i + j j = j a [ i ] [ j ] = k + + i ≥ 0 j ≥ 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 − 1 j = 0 ∑ n − i − 1 1 = 2 n ( n − 1 ) 算法实现 测试&&结果整理与文档整理
略
递归设计
定义 :一个过程或函数在定义中直接或间接调用自身的一种方法。设计关键 :找出递归关系(方程)和递归终止(边界)条件。递归关系就是使问题向边界条件转化的规则。递归设计的步骤 :
分析问题找到递归关系:找出大规模问题与小规模问题的关系,以便通过递归使问题规模变小。
设置终止条件控制递归:通过停止条件的设置,找出可解的最小规模问题。
设计函数确定数据传递方式。
例子
找出n个自然数(1,2,3,……,n)中取出r个数的所有组合。问题分析
从n个数中取出r个数共有C n C_n C n r r r 种取法。
下图所示n = 5,r = 3的情况。计算模型 { f ( i , r ) = ( 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) &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 ) f ( i , r ) = ( i , f ( i − 1 , r − 1 ) ) i = 1 , r = 1 n − 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 ∑ r C i − 1 r − 1 算法实现
附:迭代法算法实现
两者时间复杂度是一样的
基本数据结构
参考:东东ppt