動的プログラミングの質問から始める準備ができました。問題について考えるために、正直に手順に従ってください。ACMクリアランスの4つの主要なステップに従います。
- 1.ステータスを確認する
- 2.伝達方程式
- 3.初期条件と境界条件
- 4.計算順序
1.タイトルの説明
第二に、問題を解決するための動的プログラミング
これを分析することは、最も価値のある動的プログラミング問題です。
1つ:ステータスを決定する
- 最後のステップは、同じ列の前の列または同じ列の前の行から行われます。
- サブ問題:(1,1)から最後の(m、n)への移動は、(m-1、n)への移動と(m、n-1)の移動に変換されます。
- 状態を判別するには、2次元配列path [m] [n]を開いて、始点から終点までのパスの総数を表します。
2:伝達方程式
- if(m> = 1、n> = 1)、path [m] [n] = path [m-1] [n] + path [m] [n-1];
3:初期条件と境界条件
- 初期状態は
path[0][0] = 0,path[0][i]=1(i>=1),path[j][0]=1(j>=1)
です。再帰的に取得することはできませんが、計算に使用するために使用されます。 - m-1> = 0およびn-1> = 0は境界を超えることができないため、境界条件はifステートメントの値です。したがって、これを保証する必要があります。
4:計算順序 - 計算の順序は、フォームに入力する方法のプロセスです。添え字が始まる場所では、再帰に関係する値が再帰プロセスの最初に計算されるようにする必要があります。
上記の手順で、コードを書き始めました:
class Solution {
public int uniquePaths(int m, int n) {
if(m<1||n<1){
return 0;
}
if(m==1||n==1)
return 1;
int[][] path = new int[m][n];
path[0][0]=0;
for(int i=0;i<n;i++){
//边界初始化
path[0][i]=1;
}
for(int i=0;i<m;i++){
//边界初始化
path[i][0] = 1;
}
for(int i=1;i<m;i++){
for(int j = 1;j<n;j++){
path[i][j] = path[i][j-1]+path[i-1][j];
}
}
return path[m-1][n-1];
}
}
時間の複雑さ:O(m n);空間の複雑さ:O(m n);
3、スペースの複雑さを最適化
class Solution {
public int uniquePaths(int m, int n) {
int[] cur = new int[n];
Arrays.fill(cur,1);
for (int i = 1; i < m;i++){
for (int j = 1; j < n; j++){
cur[j] += cur[j-1] ;
}
}
return cur[n-1];
}
}
スペースの複雑さ:O(N);