巡礼 — LeetCode Punch 39 日目
知識のまとめ
異なるパスを使用した動的プログラミングの問題
Leetcode 62. 異なるパス
トピックの説明
ロボットは、mxn グリッドの左上隅に配置されます (下図では開始点に「開始」とマークされています)。
ロボットは一度に 1 ステップ下または右へのみ移動できます。ロボットはグリッドの右下隅 (下の画像で「終了」とマークされている) に到達しようとします。
異なるパスは合計で何通りありますか?
コードの説明
漸化式は次のとおりです。
dp[i][j] = dp[i-1][j] + dp[i][j-1];
class Solution {
public int uniquePaths(int m, int n) {
int[][] dp = new int[m][n];
for(int i =0; i < m; i++){
for(int j =0; j < n; j++){
if(i == 0 || j == 0){
dp[i][j] = 1;
}else{
dp[i][j] = dp[i-1][j] + dp[i][j-1];
}
}
}
return dp[m-1][n-1];
}
}
Leetcode 63. 異なる道 II
トピックの説明
ロボットは、mxn グリッドの左上隅に配置されます (下図では開始点に「開始」とマークされています)。
ロボットは一度に 1 ステップ下または右へのみ移動できます。ロボットはグリッドの右下隅 (下の画像で「終了」とマークされている) に到達しようとします。
ここで、グリッド内に障害物があると考えてみましょう。では、左上から右下までの異なるパスは何通りあるでしょうか?
グリッド内の障害物と空き位置は、それぞれ 1 と 0 で表されます。
コードの説明
通常バージョン。
class Solution {
public int uniquePathsWithObstacles(int[][] obstacleGrid) {
int m = obstacleGrid.length, n = obstacleGrid[0].length;
int[][] dp = new int[m][n];
if(obstacleGrid[0][0] == 1){
return 0;
}
dp[0][0] = 1;
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
if(obstacleGrid[i][j] == 1){
dp[i][j] = 0;
}else{
if(i == 0 & j == 0) continue;
int upWay =0;
int leftWay = 0;
if(i> 0){
upWay = dp[i-1][j];
}
if(j > 0){
leftWay = dp[i][j-1];
}
dp[i][j] = upWay + leftWay;
}
}
}
return dp[m-1][n-1];
}
}
スペース最適化バージョン:
class Solution {
public int uniquePathsWithObstacles(int[][] obstacleGrid) {
int m = obstacleGrid.length, n = obstacleGrid[0].length;
int[] dp = new int[n];
if(obstacleGrid[0][0] == 1 || obstacleGrid[m-1][n-1] == 1){
return 0;
}
for(int i = 0; i < n && obstacleGrid[0][i] == 0; i++){
dp[i] = 1;
}
for(int i = 1; i < m; i++){
for(int j = 0; j < n; j++){
if (obstacleGrid[i][j] == 1){
dp[j] = 0;
}else if (j > 0){
dp[j] += dp[j-1];
}
}
}
return dp[n-1];
}
}