Leetcode面试题13.机器人的运动范围

题目描述

地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1]。一个机器人从坐标[0, 0]的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。

例如,当k为18时,机器人能够进入方格 [35, 37] ,因为3+5+3+7=18。但它不能进入方格 [35, 38],因为3+5+3+8=19。请问该机器人能够到达多少个格子?

示例1:

输入:m = 2, n = 3, k = 1
输出:3

示例2:

输入:m = 3, n = 1, k = 0
输出:1

题解

从题目上来看,就是一个传统的带条件的搜索题目。很容易想到DFS或者BFS。两者目标都是遍历整个矩阵,不同点在于搜索顺序不同。DFS是朝一个方向走到底,再回退一步,走到底,再回退,以此类推(即,栈的结果);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)
  • 空间复杂度: 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)
  • 空间复杂度: O ( n m ) O(n * m)

BFS(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)
  • 空间复杂度: O ( n m ) O(n * m)
发布了50 篇原创文章 · 获赞 51 · 访问量 1972

猜你喜欢

转载自blog.csdn.net/Chen_2018k/article/details/105400338
今日推荐