1. 程式人生 > >java 數字三角形

java 數字三角形

1. 實踐題目

7-1 數字三角形

2. 問題描述

給定一個由 n行數字組成的數字三角形如下圖所示。試設計一個演算法,計算出從三角形 的頂至底的一條路徑(每一步可沿左斜線向下或右斜線向下),使該路徑經過的數字總和最大。

3. 演算法描述(不能貼上程式)

 



用一個二維陣列來儲存資料,從底向上的進行疊加,從b[i][j]出發,下一步只能是 b[i-1][j]或者b[i-1][j+1],每算一個maxSum(r,j)就儲存起來,下次用到時就直接取用,避免了重複計算的問題。成為記憶遞迴型的動態規劃。

遞迴公式:


原問題的最優值是 b[1][1]

終止條件是 b[1][1]

4. 演算法時間及空間複雜度分析(要有分析過程)

時間複雜度為O(n2),因為三角形的數字總和為n(n+1)/2,需要兩次迴圈。

空間複雜度S(n*n),因為需要一個二維陣列來存放資料

5. 程式執行截圖

 

6.心得體會(對本次實踐收穫及疑惑進行總結)

動態規劃就是聰明的窮舉法,以及聰明的分治法。都是把原問題分成若干子問題。

若子問題都不會重複,就使用分治法解決。若出現重疊子問題,就用動態規劃。如果用分治法,將會浪費大量時間進行重複求解子問題,不停的採用遞迴方法,程式就會超時。

那麼從時間上優化,就可以想到如果每算出一個MaxSum(r,j)就儲存起來,下次用到其值的時候直接取用,則可免去重複計算。使之成為記憶遞迴型的動態規劃。

如果從空間上優化,一開始我採用的是二維陣列存取資料的方法,最優條件為

b[1][1],(此時空間複雜度為S(n*n))。

maxSum[i][j] = max(maxSum[i+1][j],maxSum[i+1][j+1]) + D[i][j];    

cout << maxSum[1][1] << endl;

後來覺得二維陣列浪費儲存空間,就用一個一維陣列來儲存。從底層一行行向上遞推,即只要儲存一行的MaxSum值就可以。(此時空間複雜度為S(n))。

maxSum[j] = max(maxSum[j],maxSum[j+1]) + D[i][j];    

cout << maxSum[1] << endl;

通過以上兩個優化除錯,充分體現了原問題的最優解包含了子問題的最優解。