JZ13 机器人的运动范围
(较难)
题目
思路1:DFS
本文题意为从 [0,0] 开始遍历到[rows-1, cols-1],遇到数位和大于给定的 threshold 值的坐标位置就相当于死路,也可理解为像是边界一样的墙,此题虽说是可以向上下左右四个方向走,但是其实只要向右或者下走就可以了,这点需要意会,而此题解法又是属于一种很明显的深度优先遍历思想,因此递归的终止条件就可以是遇到内部墙或是超出边界墙,就返回 0,之所以返回 0,是因为本题要求计数可以到达的坐标总个数,因为当前遇到内部墙,因此此坐标的这种情况自然就不应被计数进去,而对于当前坐标没有遇到内部墙,又没有超出边界墙,这时可以返回其子情况的计数结果 + 1,1 表示的是当前坐标的这种情况。
注意:必须要加一个记录是否 [row, col] 坐标被访问过的标识数组,例如 boolean[][] visited 数组,因为其递归的子情况,下递归、右递归可能出现重复计数过同一坐标的情况,因此要进行标识,这也是进行深度优先遍历务必要考虑的一件事。
实现
public class JZ13机器人的运动范围 {
    int threshold = 0;
    int rows = 0;
    int cols = 0;
    boolean[][] visited = null;
    public int movingCount(int threshold, int rows, int cols) {
        this.threshold = threshold;
        this.rows = rows;
        this.cols = cols;
        this.visited = new boolean[rows][cols];
        return moving(0, 0);
    }
    public int moving(int row, int col) {
        //返回:位数不符合、边界、访问过
        if (digitSum(row, col) > threshold
                || row >= rows || col >= cols
                || visited[row][col]) return 0;
        //标注这个格子被访问过
        visited[row][col] = true;
        //子情况 + 当前情况的1次
        return moving(row + 1, col) + moving(row, col + 1) + 1;
    }
    public int digitSum(int num1, int num2) {
        int sum = 0;
        String total = "" + num1 + num2;
        char[] digits = total.toCharArray();
        for (char digit : digits) {
            sum += Integer.parseInt(digit + "");
        }
        return sum;
    }
}
思路2:BFS
BFS 的思想也十分基础, 借助一个队列实现,之前文章讲解过 BFS 的思路(Java实现【邻接矩阵、邻接表的创建、遍历(DFS,BFS)】+图解+完整代码,当时是用图结构来写的,而这里无非就是向下向右两条路线,可理解为出度为 2 的图),这里不再赘述。
实现
public class Test {
    public int movingCount(int threshold, int rows, int cols) {
        boolean[][] visited = new boolean[rows][cols];
        int count = 0;
        Queue<int[]> queue = new LinkedList<>();
        queue.add(new int[]{0, 0});
        while (queue.size() > 0) {
            int[] next = queue.poll();
            int row = next[0], col = next[1];
            //返回:位数不符合、边界、访问过
            if (row >= rows || col >= cols || threshold < digitSum(row, col) || visited[row][col])
                continue;
            //标注这个格子被访问过
            visited[row][col] = true;
            count++;
            //下边坐标
            queue.add(new int[]{row + 1, col});
            //右边坐标
            queue.add(new int[]{row, col + 1});
        }
        return count;
    }
    public int digitSum(int num1, int num2) {
        int sum = 0;
        String total = "" + num1 + num2;
        char[] digits = total.toCharArray();
        for (char digit : digits) {
            sum += Integer.parseInt(digit + "");
        }
        return sum;
    }
}
JZ17 打印从1到最大的n位数
(简单)
题目
描述
 输入数字 n,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3,则打印出 1、2、3 一直到最大的 3 位数 999。
 1、用返回一个整数列表来代替打印
 2、n 为正整数
示例
 输入:
 1
 返回值:
 [1,2,3,4,5,6,7,8,9]
思路
此题用 Java 语言实现起来十分容易,将读入的 n 位数生成 n 个 9,组成一个数,那么这个数就是当前 n 位数中最大的,那么我们返回 1 到这个数的数组即可。
实现
public class JZ17打印从1到最大的n位数 {
    public int[] printNumbers (int n) {
        int digit = Integer.parseInt(n + "");
        String maxString = "";
        for (int i = 0; i < digit; i++) {
            maxString += "9";
        }
        int max = Integer.parseInt(maxString);
        int[] res = new int[max];
        for (int i = 0; i < res.length; i++) {
            res[i] = i + 1;
        }
        return res;
    }
}
                









