記事ディレクトリ
タイトルの説明
グランドの座標から、m行n列を市松[0,0]
座標[m-1,n-1]
。ロボット[0, 0]
は座標のグリッドから移動を開始します。ロボットは一度に1つのグリッドを左、右、上、下に移動できます(グリッドを超えて移動することはできません)。また、行と列の座標の合計がkより大きいグリッドに入ることができません。
たとえば、kが18の場合、3 + 5 + 3 + 7 = 18であるため、ロボットは正方形[35、37]に入ることができます。しかし、3 + 5 + 3 + 8 = 19であるため、正方形[35、38]に入ることができません。ロボットが到達できるグリッドはいくつですか?
例1:
入力:m = 2、n = 3、k = 1
出力:3
例2:
入力:m = 3、n = 1、k = 0
出力:1
解決策
観点から見ると、これは従来の条件付き検索質問です。DFSやBFSを考えるのは簡単です。両方の目的は、行列全体を走査することです。違いは、検索順序が異なることです。DFSは1方向に進み、1ステップ戻り、最後に戻り、次に戻る、というように(つまり、スタックの結果)、BFSは行ごとに前方を検索します。
最適化の観点からは、上、下、左、右の場合がありますが、開始点がに[0,0]
あるため、下と右の状況のみを考慮する必要があります。
DFS(java)
DFS
class Solution {
int max = 0;
public boolean into(int a, int b, int k) {
int count = 0;
while (a > 0) {
count += a % 10;
a = a / 10;
}
while (b > 0) {
count += b % 10;
b = b / 10;
}
if (count <= k) {
return true;
} else {
return false;
}
}
public void step(int a, int b, int m, int n, int k, int[][] flag) {
if (flag[a][b] == 1) return;
//判断右侧有无格子且根据k能否进入
if (a + 1 < m && into(a + 1 ,b ,k)) {
step(a + 1, b, m, n, k, flag);
}
//判断下侧有无格子且根据k能否进入
if (b + 1 < n && into(a, b + 1,k)) {
step(a, b + 1, m, n, k, flag);
}
flag[a][b] = 1;
max += 1;
}
public int movingCount(int m, int n, int k) {
int[][] flag = new int [m][n];
step(0, 0, m, n, k, flag);
return max;
}
}
複雑さの分析
- 時間の複雑さ:
- スペースの複雑さ:
DFS2(Java)
DFSも同じですが、書き込み方法は明らかにかなり最適化されています。
class Solution {
public int movingCount(int m, int n, int k) {
//设置辅助数组
boolean[][] visited = new boolean[m][n];
//返回结果
return dfs(0, 0, m, n, k, visited);
}
public int dfs(int i, int j, int m, int n, int k, boolean[][] visited) {
//把所有限制条件用||来连接起来
if(i >= m || j >= n || k < getSum(i) + getSum(j) || visited[i][j]) {
return 0;
}
visited[i][j] = true;
// 每次返回值加一
return 1 + dfs(i + 1, j, m, n, k, visited) + dfs(i, j + 1, m, n, k, visited);
}
private int getSum(int a) {
int sum = a % 10;
int tmp = a / 10;
while(tmp > 0) {
sum += tmp % 10;
tmp /= 10;
}
return sum;
}
}
- 時間の複雑さ:
- スペースの複雑さ:
FSO(java)
bfsテンプレートを貼り付けて、先入れ先出しでスペースをトラバースします。
while queue 不空:
cur = queue.pop()
for 节点 in cur的所有相邻节点:
if 该节点有效且未访问过:
queue.push(该节点)
この考えによれば、書き方は以下の通りです
class Solution {
//计算数位之和
private int getSum(int a) {
int count = 0;
while (a > 0) {
count += a % 10;
a = a / 10;
}
return count;
}
public int movingCount(int m, int n, int k) {
// 辅助数组,默认值为false。(同int[][],默认为0)
boolean[][] visited = new boolean[m][n];
int res = 0;
//BFS
Queue<int[]> queue= new LinkedList<int[]>();
// 初始化,同new int[4]
queue.add(new int[] { 0, 0, 0, 0 });
while(queue.size() > 0) {
int[] x = queue.poll();
int i = x[0], j = x[1], si = x[2], sj = x[3];
if(i >= m || j >= n || k < si + sj || visited[i][j]) continue;
visited[i][j] = true;
res ++;
//添加相邻位置
queue.add(new int[] { i + 1, j, getSum(i + 1), getSum(j) });
queue.add(new int[] { i, j + 1, getSum(i), getSum(j + 1) });
}
return res;
}
}
- 時間の複雑さ:
- スペースの複雑さ: