LeetCode動的計画法における三角形の最小経路和

一緒に書く習慣をつけましょう!「ナゲッツデイリーニュープラン・4月アップデートチャレンジ」に参加して4日目です。クリックしてイベントの詳細をご覧ください

トピック

三角形の最小経路合計

三角形が与えられた場合triangle、最小のトップダウンパスの合計を見つけます。

各ステップは、次の行の隣接するノードにのみ移動できます。ここで隣接するノードとは、添え字が前のレイヤーのノードの添え字と同じか、前のレイヤーのノードの添え字+1に等しい2つのノードを指します。つまり、現在の行のインデックスiにいる場合、次のステップは次の行のインデックスiまたはi+1に移動できます。

 

例1:

输入:triangle = [[2],[3,4],[6,5,7],[4,1,8,3]]
输出:11
解释:如下面简图所示:
   2
  3 4
 6 5 7
4 1 8 3
自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。
复制代码

例2:

输入:triangle = [[-10]]
输出:-10
复制代码

ヒント:

1 <= triangle.length <= 200
triangle[0].length == 1
triangle[i].length == triangle[i - 1].length + 1
-104 <= triangle[i][j] <= 10^4
复制代码

答え

問題解決分析

問題解決のアイデア

  1. この問題では、特定の三角形の行数はnであり、i番目の行(00から番号が付けられている)にはi+1数。各行の左端を揃えると、次のように直角二等辺三角形が形成されます。
[2] 
[3,4] 
[6,5,7] 
[4,1,8,3]
复制代码
  1. f [i] [j]を使用して、三角形の上部から位置(i、j)までのパスの最小合計を示します。ここでの位置(i、j)は、三角形の行iと列j(両方とも0から始まる)の位置を指します。各行は次の行の[隣接ノード]にのみ移動できるため、位置(i、j)に移動する場合、前のステップは位置(i-1、j-1)または位置( i-1、j)。これら2つの位置のうち、パスが最も小さいものを選択して転送します。

  2. 状態遷移方程式:

f[i][j] = min(f[i-1][j-1], f[i-1][j]) + c[u]
复制代码

ここで、c [i] [j]は、位置(i、j)に対応する要素値を表します。

注:i番目の行にはi + 1個の要素があり、それらは[0、i]の範囲のjに対応します。j=0またはj=iの場合、上記の状態遷移方程式の一部の項は無意味です。たとえば、j = 0の場合、f [i-1] [j-1]には意味がないため、状態遷移方程式は次のようになります。

f[i][0] = f[i-1][0] + c[i][0]
复制代码
  1. つまり、行iの左端にいるときは、i-1行。j=if[i-1]無意味である場合、状態遷移方程式は次のようになります。
f[i][i] = f[i-1][i-1] + c[i][i]
复制代码

つまり、i行の右端にいるときは、行i-1右端からしか移動できません。

最終的なf[n-1][0]答えf[n-1][n-1]はtoの最小値です。ここで、nは三角形の行数です。

  1. 注:状態遷移方程式の境界条件は何ですか?すべての「無意味な」状態を削除したので、境界条件は次のように定義できます。
f[0][0]=c[0][0]
复制代码

つまり、三角形の上部では、最小パスの合計は、対応する位置の要素値に等しくなります。このように、1から始まるiを増分的に列挙し、。[0, i]の。

複雑さ
時間計算量:O(N ^ 2)
空間計算量:O(N ^ 2)

問題解決コード

問題を解決するためのコードは次のとおりです(コードには詳細なコメントがあります。今回はC言語を使用して質問に回答することに注意してください)。

int minimumTotal(int** triangle, int triangleSize, int* triangleColSize){
    int f[2][triangleSize];
    memset(f, 0, sizeof(f));
    // 初始化值
    f[0][0] = triangle[0][0];

    for (int i=1; i < triangleSize; i++) {
        int curr = i %2;
        int prev = 1 - curr;
        f[curr][0] = f[prev][0] + triangle[i][0];
        for (int j = 1; j < i; j++) {
            f[curr][j] = fmin(f[prev][j-1], f[prev][j]) + triangle[i][j];
        }
        f[curr][i] = f[prev][i-1] +  triangle[i][i];
    }
    
    int ret = f[(triangleSize  -1) %2] [0];

    for (int i =1; i< triangleSize; i++) {
            ret = fmin(ret, f[(triangleSize - 1) %2][i]);
    }
    return ret;
}
复制代码

提出後のフィードバック結果:

image.png

参考情報

おすすめ

転載: juejin.im/post/7082758586987724807