剑指Offer刷题笔记 13(涉及到BFS、DFS)

题目:机器人的运动范围
剑指Offer刷题笔记 13(涉及到BFS、DFS)_第1张图片
答案:

参考链接:BFS+DFS

矩阵路径的求解方法可以归结为图或树的遍历/搜索方法,而图的通用搜索算法就是BFS(广度优先搜索)和DFS(优先搜索)。

1.深度优先算法

DFS遍历节点时,满足本题条件则计数符加1,并设置该节点标志为true,同时判断该节点的子节点是否也满足本题条件,进行递归操作。

class Solution {
    public int movingCount(int m, int n, int k) {
        boolean[][] isViewed = new boolean[m][n]; 
        //计数符
        int[] count = new int[1];
        dfs(m, n, k, 0, 0, count, isViewed);
        return count[0];
    }

    //深度优先搜索
    private static void dfs(int m, int n, int k, int i, int j, int[] count, boolean[][] visit) {
        //满足位数和小于k
        if (sum(i) + sum(j) <= k) {
            //满足条件的数量+1
            count[0]++;
            //该格子被访问过
            visit[i][j] = true;

            //判断向右+1:(i+1, j),在矩阵内,且未被访问过
            if (i + 1 >= 0 && i + 1 < m && j >= 0 && j < n && !visit[i + 1][j]) {
                dfs(m, n, k, i + 1, j, count, visit);
            }
            //判断向下+1:(i, j+1),在矩阵内,且未被访问过
            if (i >= 0 && i < m && j + 1 >= 0 && j + 1 < n && !visit[i][j + 1]) {
                dfs(m, n, k, i, j + 1, count, visit);
            }
        }
    }
    //计算整数位数和函数
    private static int sum(int n) {
        int s = 0;
        while (n > 0) {
            s += n % 10;
            n /= 10;
        }
        return s;
    }

}

2.广度优先算法

BFS算法使用队列实现,当队列不为空,即取出队列的队首节点,并计数符加1,同时判断该节点的子节点是否满足题目条件,如果满足则push到队列的队尾,循环继续。本题从(0,0)开始,所以只需考虑向右(x+1,y)和向下(x,y+1)。

class Solution {
    public int movingCount(int m, int n, int k) {
        boolean[][] isViewed = new boolean[m][n]; 
        //计数符
        int[] count = new int[1];
        Queue<int[]> queue= new LinkedList<int[]>();
        queue.add(new int[] {0, 0});
        bfs(m, n, k, count, isViewed, queue);
        return count[0];
    }

    //广度优先搜索
    private static void bfs(int m, int n, int k, int[] count, boolean[][] visit, Queue<int[]> queue) {
        while (!queue.isEmpty()) {
            //取出队首节点
            int[] p = queue.poll();
            //将计数+1
            count[0]++;
            int i = p[0];
            int j = p[1];

            if (i + 1 >= 0 && i + 1 < m && j >= 0 && j < n &&
                sum(i + 1) + sum(j) <= k && !visit[i + 1][j]) {
                queue.add(new int[] {i+1, j});
                visit[i + 1][j] = true;
            }

            if (i >= 0 && i < m && j + 1 >= 0 && j + 1 < n &&
                sum(i) + sum(j + 1) <= k && !visit[i][j + 1]) {
                queue.add(new int[] {i, j+1});
                visit[i][j + 1] = true;
            }
        }
    }
    //计算整数位数和函数
    private static int sum(int n) {
        int s = 0;
        while (n > 0) {
            s += n % 10;
            n /= 10;
        }
        return s;
    }

}

你可能感兴趣的:(剑指Offer)