【算法】迭代法

简单迭代运算

**迭代(辗转法)**是一种不断用变量的旧值递推新值的过程

分类

  • 精确迭代:杨辉三角、内在移动算法等
  • 近似迭代:二分法和牛顿迭代法等

设计方法

  1. 确定迭代模型
    根据问题描述,抽象出当前值和下一个值的迭代关系。这一迭代关系应该最终收敛于所期望的目标。迭代模型时解决迭代问题的关键。
  2. 控制迭代过程
    迭代模型会包含期望的目标,根据这一目标控制迭代的次数,并最终结束算法。迭代过程的控制通常分为两种情况:一种是已知或可以计算出来迭代的次数,这时可以构建一个固定次数的循环来实现对迭代过程的控制。另一种是所需的迭代次数无法确定,需要分析出迭代过程的结束条件,还要考虑有可能得不到目标解(迭代不收敛)的情况,避免出现迭代过程的死循环。

例题

1

例题1】输出杨辉三角形
问题分析
利用一个n*n的矩阵存储信息。如下
在这里插入图片描述
a i , j = a i 1 , j 1 + a i 1 , j a_{i,j} = a_{i-1,j-1} + a_{i-1,j}
计算模型
{ a i , i = 1 a i , 0 = 1 a i , j = a i 1 , j 1 + a i 1 , j i > 1 1 j < i \left\{ \begin{array}{lr} a_{i,i} = 1& & \\ a_{i,0}=1\\ a_{i,j} = a_{i-1,j-1}+a_{i-1,j}&i>1且 1\leq j<i & \end{array} \right.
算法设计与描述
输入: n n
输出:杨辉三角
step1: 输入 n n ,定义一个n × \times n的存储矩阵 a a
step2: 令 a 0 , 0 = 1 , a 1 , 0 = 1 , a 1 , 1 = 1 a_{0,0} = 1,a_{1,0} = 1,a_{1,1} = 1 , 定义 i = 2 i = 2
step3: 令 a i , 0 = 1 , a i , i = 1 a_{i,0} = 1,a_{i,i} = 1 ,定义 j = 1 j = 1
step4: 令 a i , j = a i 1 , j 1 + a i 1 , j , j = j + 1 a_{i,j} = a_{i-1,j-1}+a_{i-1,j},j = j + 1 ,若 j < i j<i ,转step4
step5: 令 i = i + 1 i = i + 1 ,若 i < n i < n 转step3
step6: 打印输出矩阵 a a ,算法结束
算法分析

  1. 输入 n n ,规模为 n n
  2. 核心操作: a i , j = a i 1 , j 1 + a i 1 , j a_{i,j} = a_{i-1,j-1}+a_{i-1,j}
  3. 得出 T ( n ) = i = 2 n 1 ( 2 + j = 1 i 1 1 ) + 3 = Θ ( n 2 ) T(n) = \sum_{i=2}^{n-1}(2 + \sum_{j=1}^{i-1}1)+3 = \Theta(n^2)

2

例题2内存移动问题:数组中有n个数据,要将它们顺序循环向后移k位,即前面的元素向后(右)移k位,后面的元素则循环向前移k位,例:0、1、2、3、4、5循环移3位后为: 3、4、5、0、1、2。考虑到n会很大,不允许用2*n及以上个空间来完成此题。
问题分析
设原数列为 a [ n ] a[n] ,移动k次。

  1. 建立一个数列 b [ n ] b[n] ,令 b [ ( k + i )    m o d    n ] = a [ i ] , i [ 0 , n 1 ] b[(k+i)\;mod\;n] = a[i] , i \in [0,n-1]
    此时,时间复杂度为 O ( n ) O(n) ,空间复杂度为 O ( 2 n ) O(2n) ,不符合题目要求。
  2. 建立临时变量 t m p tmp ,令 t m p = a [ n 1 ] tmp = a[n-1] ,然后从 a [ n 2 ] a[n-2] 开始所有位右移一位,最后,令 a [ 0 ] = t m p a[0]=tmp ,实现右移一位,循环实现右移k位。
    此时,时间复杂度为 O ( k × n ) O(k\times n) ,空间复杂度为 O ( n + 1 ) = O ( n ) O(n+1) = O(n)
  3. 如果按照2的方法将元素直接移动至指定位置,那么时间复杂度为 O ( n ) O(n) ,空间复杂度为 O ( n ) O(n)
    如:n = 6,k = 3的情况,将 a [ 0 ] a [ 3 ] a[0]\to a[3] , a [ 3 ] a [ 0 ] a[3]\to a[0] ; a [ 1 ] a [ 4 ] a[1]\to a[4] , a [ 4 ] a [ 1 ] a[4]\to a[1] , a [ 2 ] a [ 5 ] a[2]\to a[5] , a [ 5 ] a [ 2 ] a[5]\to a[2] ,共需要移动3轮,每轮移动元素个数为2。
    不难发现,此时
    = g c d ( n , k ) 移动轮数 = gcd(n,k)
    下面给出证明
    g c b ( n , k ) = q gcb(n,k) = q ,每轮最少移动元素个数为 r r
    从而有: n = q × n 1 , k = q × n 2 n 1 , n 2 Z n = q \times n_1 , k = q \times n_2\quad n_1,n_2\in Z g c b ( n 1 , n 2 ) = 1 gcb(n_1,n_2) = 1
    由每轮第一次移动的元素要和最后一次移动到的元素相同可得: ( k × r )    m o d    n = 0 (k\times r)\; mod\; n = 0
    从而推出: ( n 2 × r )    m o d    n 1 = 0 (n_2\times r)\; mod\; n_1 = 0
    g c b ( n 1 , n 2 ) = 1 gcb(n_1,n_2) = 1 可得: g c b ( n 1 , r ) = n 1 gcb(n_1,r) = n_1
    r r 为每轮最小移动次数,取 n 1 n_1 ,此时移动轮数为 n / r = q n/r = q

下文主要讲述第三种方法
计算模型

  1. 求出最大公约数,由欧几里得
    { a , b = b , a b > a r = a    m o d    b g c d ( a , b ) = g c b ( b , r ) r 0 g c d ( a , b ) = b r = 0 \left\{ \begin{array}{lr} a,b = b,a & 若b>a& 初始化\\ r = a\; mod\; b & & 进入循环 \\ gcd(a,b) = gcb(b,r) &r \not= 0&判断\\ gcd(a,b) = b &r = 0& 结束 \end{array} \right.
  2. q = g c b ( a , b ) q = gcb(a,b) [上一步所求出来的], 移动次数: i = n / q i = n/q
  3. 计算元素移动位置: x i = ( x m + i × k )    m o d    n 0 i < n / q 0 x m < q x_i = (x_m + i\times k)\; mod\; n\quad 0\leq i<n/q \quad 0 \leq x_m < q
    说明:初始元素为 x m x_m ,第 i i 次移动实现 a [ x i 1 ] a [ x i ] a[x_{i-1}]\to a[x_i] ,共移动 q q

算法设计与描述
在这里插入图片描述
算法分析
在这里插入图片描述
注:可以进行改进,减少内层循环次数。

例题3】求n!(n<=100)
问题分析
int整数表示的范围为:-2147483648 —— -2147483647,显然不能直接处理规模为100的阶乘计算。所以需要借助一个int型数组a,设定每个元素存储6位整数,由式子 l o g ( n ! ) = Θ ( n log n ) log(n!) = \Theta(n\log n) 可得数组中约需要34个元素。
计算方法:模拟竖式乘法
计算模型
设存储大数结果的数组为 a [ m ] a[m] m = n ( log n ) / 6 m = n (\log n)/6
初始化 a [ 0 ] = 1 a [ i ] = 0 ( i 0 ) a[0] =1,a[i] = 0 (i\not=0)

算法设计与描述
在这里插入图片描述
算法分析
在这里插入图片描述
注:可以进行改进,减少内层循环次数。

例题3】求n!(n<=100)
问题分析
int整数表示的范围为:-2147483648 —— -2147483647,显然不能直接处理规模为100的阶乘计算。所以需要借助一个int型数组a,设定每个元素存储6位整数,由式子 l o g ( n ! ) = Θ ( n log n ) log(n!) = \Theta(n\log n) 可得数组中约需要34个元素。
计算方法:模拟竖式乘法
计算模型
设存储大数结果的数组为 a [ m ] a[m] m = n ( log n ) / 6 m = n (\log n)/6
初始化 a [ 0 ] = 1 a [ i ] = 0 ( i 0 ) a[0] =1,a[i] = 0 (i\not=0)
{ b = a [ j ] × i + d 1 j m , 1 < i n b a [ j ] = b    m o d    1000000 1 j m a [ j ] d = b 1000000 i ] ,共移动 q q

算法设计与描述
在这里插入图片描述
算法分析
在这里插入图片描述
注:可以进行改进,减少内层循环次数。

例题3】求n!(n<=100)
问题分析
int整数表示的范围为:-2147483648 —— -2147483647,显然不能直接处理规模为100的阶乘计算。所以需要借助一个int型数组a,设定每个元素存储6位整数,由式子 l o g ( n ! ) = Θ ( n log n ) log(n!) = \Theta(n\log n) 可得数组中约需要34个元素。
计算方法:模拟竖式乘法
计算模型
设存储大数结果的数组为 a [ m ] a[m] m = n ( log n ) / 6 m = n (\log n)/6
初始化 a [ 0 ] = 1 a [ i ] = 0 ( i 0 ) a[0] =1,a[i] = 0 (i\not=0)
{ b = a [ j ] × i + d 1 j m , 1 < i n b a [ j ] = b    m o d    1000000 1 j m a [ j ] d = b 1000000 a [ m ] a[m] m = n ( log n ) / 6 m = n (\log n)/6

相关文章
相关标签/搜索