【算法】迭代法

簡單迭代運算

**迭代(輾轉法)**是一種不斷用變量的舊值遞推新值的過程

分類

  • 精確迭代:楊輝三角、內在移動算法等
  • 近似迭代:二分法和牛頓迭代法等

設計方法

  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

相關文章
相關標籤/搜索