(動態規劃)給定三角形,找到從上到下的最小路徑總和

Kobe10發表於2017-02-02
  • 題目:
    給定一個三角形,找到從上到下的最小路徑總和。 您可以將每個步驟移動到下面一行中的相鄰數字。
    
    例如,給定以下三角形
    
    [
          [2],
         [3,4],
        [6,5,7],
       [4,1,8,3]
    ]]
    
    
    從頂部到底部的最小路徑總和為11(即,2 + 3 + 5 + 1 = 11)。
    
    注意:
    獎勵點,如果你能夠使用只使用O(n)額外的空間,其中n是三角形中的總行數。

     

  • 思路:
    • 第一種解法:這個題目提示是用DP去做。這裡一般的思路是使用二維陣列去儲存每一層與上一層想加的最小值得和。有兩種遍歷方式,從下到上和從上到下。第一種遍歷方式比較簡單。第二種方式需要考慮比較多的因素。
    • 程式碼
      //從上到下遍歷
      class Solution {
      public:
          int minimumTotal(vector<vector<int> > &triangle) {
              int row = triangle.size();
              vector<vector<int> > path(row);//申請行空間,二維陣列
              for (int i=0; i<row; i++)
                  path[i].resize(triangle[i].size(), 0);//申請列空間
              //path[0][0] = triangle[0][0];
              int col = 0;
              for (int i=0; i<row; i++){
                  col = triangle[i].size();
                  for (int j=0; j<col; j++){
                      if (0 == i)
                          path[i][j] = triangle[i][j];
                      else{
                          if (j == 0)
                              path[i][j] = path[i-1][j] + triangle[i][j];
                          else if (j == (col-1))
                              path[i][j] = path[i-1][j-1] + triangle[i][j];
                          else
                              //當不是首尾數字的時候,看上一層相鄰的兩個數哪個更小更適合想加
                                 path[i][j] = min(path[i-1][j-1], path[i-1][j]) + triangle[i][j];
                      }
                  } 
              }
              int Min = path[row-1][0];
              for (int i=0 ;i<path[row-1].size(); i++)
                  if (Min > path[row-1][i])
                      Min = path[row-1][i];
                 return Min;
          }
      };
      //從下到上遍歷
      class Solution {
      public:
          int minimumTotal(vector<vector<int> > &triangle) {
              int row = triangle.size();
              vector<vector<int> > path(row);//申請行空間,二維陣列
              int num = 0;
              for (int i=row-1; i>=0; i--)
                  path[num++].resize(triangle[i].size(), 0);//申請列空間 
              int col = 0;
              int s = row;
              for (int i=0; i<row; i++){
                  s--;
                  col = triangle[s].size();
                  for (int j=0; j<col; j++){
                      if (0 == i)
                          path[i][j] = triangle[s][j];
                      else{
                          //當不是首尾數字的時候,看上一層相鄰的兩個數哪個更小更適合想加
                             path[i][j] = min(path[i-1][j], path[i-1][j+1]) + triangle[s][j];
                      }
                  } 
              }
                 return path[row-1][0];
          }
      };
    • 第二種解法:在原有空間的基礎上直接進行運算,不用重新名稱空間了。程式碼比較簡潔,但是效率好像不是很高。

相關文章