記事ディレクトリ
1. タイトル
ロボットがグリッドの左上隅、r 行、c 列に座っていると想像してください。ロボットは下または右にのみ移動できますが、一部の禁止されたグリッド (障害物がある) には移動できません。ロボットが左上隅から右下隅まで移動する経路を見つけるアルゴリズムを設計します。
グリッド内の障害物と空いている場所は、それぞれ1
とで表されます0
。
通過したグリッドの行番号と列番号で構成される実行可能なパスを返します。左上隅は行 0、列 0 です。実行可能なパスがない場合は、空の配列が返されます。
例 1:
入力:
[
[0,0,0],
[0,1,0],
[0,0,0]
]
出力: [[0,0],[0,1],[0,2],[1] ,2],[2,2]]
説明:
入力内の太字の位置は出力で表されるパスです。つまり、
0 行 0 列 (左上隅) -> 0 行 1 列 -> 0 行です。 2 列 -> 1 行 2 列 -> 2 行 2 列 (右下隅)
注: r と c の値は 100 を超えません。
2. C# の問題の解決策
バックトラッキング ソリューションを使用することもできますが、ここでは動的プログラミングの方が適しています。path は現在位置が終点まで到達できるかどうかを記録するもので、終点から始点までを基準に判断し、現在の値はpath[i, j]
障害obstacleGrid[i][j] == 0 && (path[i + 1, j] || path[i, j + 1])
物がなく、後方に到達可能な経路があることを意味します。境界の場合は、配列が範囲外にならないように、最初に特別な処理が必要です。
public class Solution {
public IList<IList<int>> PathWithObstacles(int[][] obstacleGrid) {
int r = obstacleGrid.Length, c = obstacleGrid[0].Length;
IList<IList<int>> ans = new List<IList<int>>();
bool[,] path = new bool[r, c]; // 记录可到达路径
if (obstacleGrid[r - 1][c - 1] == 1) return ans; // 如果终点有障碍物,直接返回空
/* 动态规划求解可到达路径 */
path[r - 1, c - 1] = true;
// 最右方边界判断
for (int j = c - 2; j >= 0; j--)
if (path[r - 1, j + 1] && obstacleGrid[r - 1][j] == 0)
path[r - 1, j] = true;
// 最下方边界判断
for (int i = r - 2; i >= 0; i--)
if (path[i + 1, c - 1] && obstacleGrid[i][c - 1] == 0)
path[i, c - 1] = true;
// 中间判断
for (int i = r - 2; i >= 0; i--)
for (int j = c - 2; j >= 0; j--)
if (obstacleGrid[i][j] == 0 && (path[i + 1, j] || path[i, j + 1]))
path[i, j] = true;
if (!path[0, 0]) return ans; // 如果起点没有可到达路径,返回空
/* 求解一条可到达路径 */
int x = 0, y = 0;
while (x != r - 1 || y != c - 1) {
ans.Add(new List<int> {
x, y }); // 添加路径
if (y + 1 < c && path[x, y + 1]) y++; // 优先向右走
else x++; // 右方堵住则向下走
}
ans.Add(new List<int> {
r - 1, c - 1 }); // 添加终点
return ans;
}
}
- 時間: 132 ミリ秒、C# を使用しているユーザーの 100.00% を上回ります
- メモリ: 42.62 MB、C# を使用しているユーザーの 100.00% を上回る