leetcode 120 三角形最小路徑和

溫酒煮Bug發表於2019-01-23

描述:

給定一個三角形,找出自頂向下的最小路徑和。每一步只能移動到下一行中相鄰的結點上。

例如,給定三角形:

[
     [2],
    [3,4],
   [6,5,7],
  [4,1,8,3]
]
複製程式碼

自頂向下的最小路徑和為 11(即,2 + 3 + 5 + 1 = 11)。

說明:

如果你可以只使用 O(n) 的額外空間(n 為三角形的總行數)來解決這個問題,那麼你的演算法會很加分。

思路:

這裡有兩種方法可以進行求解

1 回溯法(列舉),找到每一個值,然後返回,比較大小,找出最小值。(leetcode過不了,最後一個測試用例會超時)

2 動態規劃:

  • 定義狀態dp[i][j]:從底層到triange[i][j]的路徑,找到最小值。
  • 狀態轉移方程:dp[i][j] = triangle[i][j] + min(dp[i+1][j],dp[i+1][j+1])。
  • 定義初始值:底層不變,逐步向上進行推進。

程式碼1:

class Solution {
  int min = Integer.MAX_VALUE;
  int sum = 0;

  public int minimumTotal(List<List<Integer>> triangle) {
    int i = 0, j = 0;
    helper(triangle, i, j);
    return min;
  }

  private void helper(List<List<Integer>> triangle, int i, int j) {
    if (i == triangle.size()) {
      min = Math.min(sum, min);
      return;
    }
    sum += triangle.get(i).get(j);
    helper(triangle, i + 1, j);
    helper(triangle, i + 1, j + 1);
    sum -= triangle.get(i).get(j);
  }
}
複製程式碼


結果1:

leetcode 120 三角形最小路徑和

程式碼2:

class Solution {
  public int minimumTotal(List<List<Integer>> triangle) {
    int[] mini = new int[triangle.size() + 1];
    for (int i = triangle.size() - 1; i >= 0; i--) {
      for (int j = 0; j < triangle.get(i).size(); j++) {
        mini[j] = triangle.get(i).get(j) + Math.min(mini[j], mini[j + 1]);
      }
    }
    return mini[0];
  }
}
複製程式碼


結果2:

leetcode 120 三角形最小路徑和

總結:

回溯法,需要把整個陣列的每一條路徑都遍歷一遍,時間複雜度是O(n的平方),最後一個測試用例會超時,但是也是一種解決問題的辦法,面試的話也可以考慮使用,程式碼非常簡潔,可讀性比較強。

動態規劃這裡用了一個小技巧,用一維陣列去記錄子問題的最優解,可以省一個維度的記憶體空間,程式碼也比較簡潔。

相關文章