算法第三章實踐報告

1.實踐題目:數字三角形 算法

 

2.問題描述:數組

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

 

3.算法描述:設計

  首先,將這個數字三角形存儲在一個二維數組num[n+1][n+1]中,且採用左下角的直角三角形的方式存儲(第0行和第0列儲存爲0,方便操做)。例如,將PTA上的樣例輸入存儲爲以下所示:遞歸

  0  0  0  0  0  0for循環

  0  7  0  0  0  0
  0  3  8  0  0  0
  0  8  1  0  0  0
  0  2  7  4  4  0
  0  4  5  2  6  5二叉樹

  而後,第1行第1列(7)開始從上到下遍歷,並將它置爲它上方的數及左上方的數的較大值與它自身的和:num[i][j] = num[i][j] + max(num[i-1][j-1], num[i-1][j]);循環

  遍歷完成後,最後一行的數都是它上面的數的較大值的總和,以PTA的樣例輸入爲例,通過上述操做之後該數組變成:遍歷

  0  0   0   0   0   0方法

  0  7   0   0   0   0 
  0 10 15  0   0   0 
  0 18 16 15  0   0 
  0 20 25 20 19  0 
  0 24 30 27 26 24

  所以所求的最大路徑就是最後一行的最大值。這裏使用簡單求數組最大值的方法找到了最大值爲30:

  int max = 0;
  for (int i = 1; i <= n; i++)
    if (num[n][i] > max)
      max = num[n][i];

3.算法時間及空間複雜度分析:

  時間複雜度:該算法在遍歷階段採用了雙層for循環進行遍歷,所以時間複雜度爲O(n^2)。

  空間複雜度:該算法是直接在原數組上操做的,所以輔助空間較少,空間複雜度爲O(1)。

 

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

  這個題目的主要難點在於如何保存數組以及寫出遞推公式。由這個數字三角形的形狀我第一反應是用二叉樹來保存,而後使用中序遍歷或前序遍從來找到最大路徑。但好像沒有預設的二叉樹的數據結構,並且操做也有諸多困難,所以我最後選擇了二維數組。這裏我用行列長度比原長度大1的方式,空出第0行和第0列,主要是爲了遞歸時的方便,不用考慮邊界的問題。好在這道題的遞推公式也不難寫,所以我按本身對動態規劃的印象寫出了num[i][j] = num[i][j] + max(num[i-1][j-1], num[i-1][j])。這道題有一個坑是咱們每每第一反應是「每次分叉都選最大值,那麼結果不就是最大路徑了嗎?」但這實際上是犯了一個常見的錯誤:認爲局部最優解就是總體最優解。例如,樣例輸入中,咱們每次分叉選擇較大值,即7+8+1+7+5=28。但實際上最優解是3+7+8+7+5=30。所以,咱們在解決相似問題的時候,必定要注意這個細節,即局部最優解並不必定等於總體最優解。

相關文章
相關標籤/搜索