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)就儲存起來,下次用到其值的時候直接取用,則可免去重複計算。使之成為記憶遞迴型的動態規劃。
如果從空間上優化,一開始我採用的是二維陣列存取資料的方法,最優條件為
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;
通過以上兩個優化除錯,充分體現了原問題的最優解包含了子問題的最優解。