Questions sur le pinceau LeetCode: BFS

guider

Expliquer la
comparaison entre BFS et DFS

Mots-clés DFS: récursivité / pile + toutes les solutions L'
implémentation de DFS repose fortement sur pile / récursivité, et il résout simplement le problème de savoir comment traverser tous les éléments et rechercher le "point final".
Cependant, bien que DFS puisse trouver le chemin d'arrivée, il ne peut pas trouver le chemin le plus court. Pour résoudre ce problème, un algorithme BFS (width first traversal) est fourni.
Et la différence DFS est que ce n'est plus chaque bifurcation de la route une par une, mais tout en traversant jusqu'à ce que vous trouviez la fin, correspondant aux "couches" est le nombre d'étapes nécessaires pour le chemin le plus court vers
la solution ci-dessus Parmi eux, si vous devez traiter tous les éléments de la file d'attente actuelle (c'est-à-dire lorsque vous avez besoin d'un concept hiérarchique), vous devez ajouter une boucle for (i <size).
Si vous ne traitez qu'un seul élément de la file d'attente à un temps (pas de concept hiérarchique), vous n'avez pas besoin d'ajouter pour le cycle

Solution universelle BFS

int BFS(Node root, Node target) {
    
    
    Queue<TreeNode> queue = new ArrayDeque<>();  // 建立队列
    int step = 0;       // 建立行动步数,通常用这个作为最短路径的返回值
    // initialize
    queue.add(root);
    // BFS
    while (!queue.isEmpty()) {
    
    
        step = step + 1;
        // 记录此时的队列大小,也即此层元素的多少
        int size = queue.size();
        for (int i = 0; i < size; ++i) {
    
     //遍历此层的所有元素
            Node cur = queue.poll();
            return step if cur is target;
            for (Node next : the neighbors of cur) {
    
    
                queue.offer(next);       //加入查找的方向,将下一层元素加入到队列中
            }
        }
    }
    return -1;          // 没有找到目标返回-1
}

Exemple

102. Traversée au niveau de l'arborescence: solution standard

Insérez la description de l'image ici

Référence:
https://leetcode-cn.com/problems/binary-tree-level-order-traversal/solution/bfs-de-shi-yong-chang-jing-zong-jie-ceng-xu-bian-l/

class Solution {
    
    
    public List<List<Integer>> levelOrder(TreeNode root) {
    
    
        List<List<Integer>> res = new LinkedList<>();
        BFS(root, res);
        return res;
    }
 
    private void BFS(TreeNode treeNode, List<List<Integer>> res) {
    
    
        if (treeNode == null) {
    
    
            return;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(treeNode);
        while (!queue.isEmpty()) {
    
    
            List<Integer> level = new LinkedList<>();
            int n = queue.size(); // 由于下方queue会一直offer,所以这里只能int提前存储下size
            for(int i = 0; i < n; i++) {
    
     // 只是为了完成本层遍历,无实际作用
                TreeNode tmp = queue.poll();
                if(tmp != null) {
    
    
                    level.add(tmp.val);
                    queue.offer(tmp.left);
                    queue.offer(tmp.right);
                }
            }
            if(level.size() > 0) {
    
    
 res.add(level); // 由于上方的level每次都是新new的,因此无需下方这种写法
                // res.add(new LinkedList<>(level));  // 这种常常用于level是传入进来的参数,防止堆污染
            }
        }
    }
}

version zigzag: deque
Insérez la description de l'image ici

public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
    
    
        List<List<Integer>> ans = new LinkedList<List<Integer>>();
        if (root == null) {
    
    
            return ans;
        }
 
        Queue<TreeNode> nodeQueue = new LinkedList<TreeNode>();
        nodeQueue.offer(root);
        boolean isOrderLeft = true;
 
        while (!nodeQueue.isEmpty()) {
    
    
            Deque<Integer> levelList = new LinkedList<Integer>();
            int size = nodeQueue.size();
            for (int i = 0; i < size; ++i) {
    
    
                TreeNode curNode = nodeQueue.poll();
                if (isOrderLeft) {
    
    
                    levelList.offerLast(curNode.val);
                } else {
    
    
                    levelList.offerFirst(curNode.val);
                }
                if (curNode.left != null) {
    
    
                    nodeQueue.offer(curNode.left);
                }
                if (curNode.right != null) {
    
    
                    nodeQueue.offer(curNode.right);
                }
            }
            ans.add(new LinkedList<Integer>(levelList));
            isOrderLeft = !isOrderLeft;
        }
 
        return ans;
    }

207. Curriculum: tri topologique

Insérez la description de l'image ici
https://leetcode-cn.com/problems/course-schedule/
Tri topologique:
Réponse:
https://leetcode-cn.com/problems/course-schedule/solution/ke-cheng-biao-by-leetcode-solution /
Article de référence: La structure de stockage des graphes et la réalisation du tri topologique
https://www.jianshu.com/p/cd24cfb6c8d0

Réponse de la version DFS:

List<List<Integer>> edges;
    int[] visited; // 状态数组。0:未处理;1:正在搜索;2:已经完成
    boolean valid = true;  // 结果存储
 
    public boolean canFinish(int numCourses, int[][] prerequisites) {
    
    
        edges = new ArrayList<List<Integer>>();
        for (int i = 0; i < numCourses; ++i) {
    
    
            edges.add(new ArrayList<Integer>());
        }
        visited = new int[numCourses];
        for (int[] info : prerequisites) {
    
    
            edges.get(info[1]).add(info[0]); // 邻接表的构建,注意直接get.add
        }
        for (int i = 0; i < numCourses && valid; ++i) {
    
     // 剪枝
            if (visited[i] == 0) {
    
    
                dfs(i);
            }
        }
        return valid;
    }
 
    public void dfs(int u) {
    
    
        visited[u] = 1; // 对当前处理位置做标记
        for (int v: edges.get(u)) {
    
    
            if (visited[v] == 0) {
    
    
                dfs(v); // 所有的子节点都满足拓扑排序,则本次处理节点必然满足。
                if (!valid) {
    
    
                    return; // 直接返回,同时保留了当前为1的状态
                }
            } else if (visited[v] == 1) {
    
    
                valid = false;
                return;
            }
        }
        visited[u] = 2; // 当前处理完成:这里不再是清理标记而是替换为另一种状态
    }

Réponse de la version BFS;

class Solution {
    
    
    List<List<Integer>> edges;
    int[] indeg; // 入度表
 
    public boolean canFinish(int numCourses, int[][] prerequisites) {
    
    
        edges = new ArrayList<List<Integer>>();
        for (int i = 0; i < numCourses; ++i) {
    
    
            edges.add(new ArrayList<Integer>());
        }
        indeg = new int[numCourses];
        for (int[] info : prerequisites) {
    
    
            edges.get(info[1]).add(info[0]);
            ++indeg[info[0]];
        }
 
        Queue<Integer> queue = new LinkedList<Integer>();
        for (int i = 0; i < numCourses; ++i) {
    
    
            if (indeg[i] == 0) {
    
    
                queue.offer(i); // 第一批入度为0的节点进入队列
            }
        }
 
        int visited = 0;
        while (!queue.isEmpty()) {
    
    
            ++visited;
            int u = queue.poll();
            for (int v: edges.get(u)) {
    
    
                --indeg[v];
                if (indeg[v] == 0) {
    
    
                    queue.offer(v); // 第二批入度为0的表进入队列
                }
            }
        }
 
        return visited == numCourses;
    }
}

994. Oranges pourries: BFS multiples

https://leetcode-cn.com/problems/rotting-oranges/solution/fu-lan-de-ju-zi-by-leetcode-solution/

Première recherche multi-source

class Solution {
    
    
        // dr,dc 配合使用得到 grid[r][c] 上grid[r-1][c]左grid[r][c-1]下grid[r+1][c]右grid[r][c+1]的元素
        int[] dr = new int[]{
    
    -1, 0, 1, 0};  // 代指四个方向,左[-1,0],上[0,-1],右[1,0],下[0,1]
        int[] dc = new int[]{
    
    0, -1, 0, 1};
public int orangesRotting(int[][] grid) {
    
    
            // 获取二维数组的行数row 和 列数 column
            int R = grid.length, C = grid[0].length;
                          // queue : all starting cells with rotten oranges
            Queue<Integer> queue = new ArrayDeque();
            Map<Integer, Integer> depth = new HashMap();
            for (int r = 0; r < R; ++r)
                for (int c = 0; c < C; ++c)
                    if (grid[r][c] == 2) {
    
    
                        int code = r * C + c;  // 转化为索引唯一的一维数组
                        queue.add(code); //存储腐烂橘子
                        depth.put(code, 0); //存储橘子变为腐烂时的时间,key为橘子的一维数组下标,value为变腐烂的时间
                    }
 
                          int ans = 0; // 存储最终结果
            while (!queue.isEmpty()) {
    
     // 处理所有感染者
                int code = queue.remove();
                int r = code / C, c = code % C;
                for (int k = 0; k < 4; ++k) {
    
    
                    // grid位置获取方式,四个方向,四种策略
                    int nr = r + dr[k];
                    int nc = c + dc[k]; 
                    if (0 <= nr && nr < R && 0 <= nc && nc < C && grid[nr][nc] == 1) {
    
    
                                            // 0 <= nr && nr < R && 0 <= nc && nc < C,代指在grid有效范围之内,grid[nr][nc] == 1新鲜要处理
                        grid[nr][nc] = 2;
                        int ncode = nr * C + nc;
                        queue.add(ncode); // 入队
                        // 计次的关键 元素 grid[r][c] 的上左下右元素得腐烂时间应该一致
                        depth.put(ncode, depth.get(code) + 1);
                        ans = depth.get(ncode);
                    }
                }
            }
 
                          //检查grid,此时的grid能被感染已经都腐烂了,此时还新鲜的橘子无法被感染
            for (int[] row: grid)
                for (int v: row)
                    if (v == 1)
                        return -1;
            return ans;
}
    }

Je suppose que tu aimes

Origine blog.csdn.net/weixin_38370441/article/details/115249006
conseillé
Classement