Leetcodeインタビューの質問13.ロボットの可動範囲

タイトルの説明

グランドの座標から、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;
    }
}

複雑さの分析

  • 時間の複雑さ: メートル O(n * m)
  • スペースの複雑さ: メートル O(n * m)

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;
    }
}
  • 時間の複雑さ: メートル O(n * m)
  • スペースの複雑さ: メートル O(n * m)

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;
    }
}
  • 時間の複雑さ: メートル O(n * m)
  • スペースの複雑さ: メートル O(n * m)
50件の元の記事を公開 賞賛された51件 1972年の訪問

おすすめ

転載: blog.csdn.net/Chen_2018k/article/details/105400338