LeetCode DFS、BFS篇(102、200、111、752)

102. 二叉树的层序遍历

给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。

示例:
二叉树:[3,9,20,null,null,15,7],

3

/
9 20
/
15 7
返回其层次遍历结果:

[
[3],
[9,20],
[15,7]
]

//思路1BFS,优化广度遍历,一层一层放进deque进行遍历,遍历完一层就用list装完加入res
//思路2DFS,每一层递归都用index做标记

solution1 BFS 迭代

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> res = new ArrayList<>();
        ArrayDeque<TreeNode> deque = new ArrayDeque<>();
        if (root != null) {
            deque.add(root);
        }
        while (!deque.isEmpty()){
            int n = deque.size();
            List<Integer> level = new ArrayList<>();
            for (int i = 0;i<n;i++){
                TreeNode node = deque.pop();
                level.add(node.val);
                if (node.left!=null){
                    deque.add(node.left);
                }
                if (node.right!=null){
                    deque.add(node.right);
                }
            }
            res.add(level);
        }
        return res;
    } 
}

solution 2 DFS 递归

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> res = new ArrayList<>();
        if (root == null){
            return res;
        }
        dfs(res,root,1);
        return res;
    }
    public void dfs(List<List<Integer>> res,TreeNode node,int index){
        if (res.size()<index){
            res.add(new ArrayList<Integer>());
        }
        res.get(index-1).add(node.val);
        if (node.left != null){
            dfs(res,node.left,index+1);
        }
        if (node.right != null){
            dfs(res,node.right,index+1);
        }
    }
}

200. 岛屿数量

给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。

岛屿总是被水包围,并且每座岛屿只能由水平方向或竖直方向上相邻的陆地连接形成。

此外,你可以假设该网格的四条边均被水包围。

示例 1:

输入:
[
['1','1','1','1','0'],
['1','1','0','1','0'],
['1','1','0','0','0'],
['0','0','0','0','0']
]
输出: 1
示例 2:

输入:
[
['1','1','0','0','0'],
['1','1','0','0','0'],
['0','0','1','0','0'],
['0','0','0','1','1']
]
输出: 3
解释: 每座岛屿只能由水平和/或竖直方向上相邻的陆地连接而成。

//思路1:用DFS把1以及周围的点变为0,用静态变量g保存grid,可以让不太的方法修改它
//思路2:用BFS将1以及周围变为0

solution1 DFS

class Solution {
    char[][] g;
    public int numIslands(char[][] grid) {
        int res = 0;
        g = grid; 
        int re = 0;
        for (int i=0; i<g.length; i++){
            for (int j=0; j < g[i].length; j++){
                if (g[i][j] == '1') {
                    sink(i,j);
                    res ++;
                }
            }
        }
        return res;
        
    }
    public void sink(int i,int j){
        //终止条件
        if(i < 0 || j < 0 || i >= g.length || j >= g[0].length || g[i][j] == '0') return;
        //当前层
        g[i][j] = '0';
        //下一层
        sink(i + 1, j);
        sink(i, j + 1);
        sink(i - 1, j);
        sink(i, j - 1);

    }
}

solution2 BFS

class Solution {
    char[][] g;
    public int numIslands(char[][] grid) {
        int res = 0;
        g = grid; 
        for (int i=0; i<g.length; i++){
            for (int j=0; j < g[i].length; j++){
                if (g[i][j] == '1') {
                    bfs(i,j);
                    res ++;
                }
            }
        }
        return res;
    }
    public void bfs(int i,int j){
        g[i][j] = '0';
        int x = g.length;
        int y=g[0].length;
        int code = i*y + j;
        ArrayDeque<Integer> deque = new ArrayDeque<>();
        deque.push(code);
        while(!deque.isEmpty()){
            code = deque.pop();
            int n = code/y;
            int m = code%y;
            if (n>0 && g[n-1][m] == '1'){
                deque.push((n-1)*y+m);
                g[n-1][m] = '0';
            }
            if (n<x-1 && g[n+1][m] == '1'){
                deque.push((n+1)*y+m);
                g[n+1][m] = '0';
            }
            if (m>0 && g[n][m-1] == '1'){
                deque.push(n*y+(m-1));
                g[n][m-1] = '0';
            }
            if (m<y-1 && g[n][m+1] == '1'){
                deque.push(n*y+(m+1));
                g[n][m+1] = '0';
            }
        }
    }
}

111. 二叉树的最小深度

给定一个二叉树,找出其最小深度。

最小深度是从根节点到最近叶子节点的最短路径上的节点数量。

说明: 叶子节点是指没有子节点的节点。

示例:

给定二叉树 [3,9,20,null,null,15,7],

3

/
9 20
/
15 7
返回它的最小深度 2.

class Solution {
    public int minDepth(TreeNode root) {
        if (root == null) return 0;
        Deque<TreeNode> dq = new LinkedList<>();
        //往队列添加元素
        dq.offer(root);
        int depth = 1;
        while( !dq.isEmpty()){
            int len = dq.size();
            //以当前队列中的所有节点向四周扩撒
            for(int i = 0; i < len; i ++){
                TreeNode node = dq.poll();
                if(node.left == null && node.right == null){
                    return depth;
                }
                if (node.left != null){
                    dq.offer(node.left);
                }
                if (node.right != null){
                    dq.offer(node.right);
                }
            }
            //增加深度
            depth++;
        }
        return depth;

    }
}
// 思路1: 运用BFS,以面单位进行搜索,使用dq进行保存

752. 打开转盘锁

你有一个带有四个圆形拨轮的转盘锁。每个拨轮都有10个数字: '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' 。每个拨轮可以自由旋转:例如把 '9' 变为 '0','0' 变为 '9' 。每次旋转都只能旋转一个拨轮的一位数字。

锁的初始数字为 '0000' ,一个代表四个拨轮的数字的字符串。

列表 deadends 包含了一组死亡数字,一旦拨轮的数字和列表里的任何一个元素相同,这个锁将会被永久锁定,无法再被旋转。

字符串 target 代表可以解锁的数字,你需要给出最小的旋转次数,如果无论如何不能解锁,返回 -1。

示例 1:

输入:deadends = ["0201","0101","0102","1212","2002"], target = "0202"
输出:6
解释:
可能的移动序列为 "0000" -> "1000" -> "1100" -> "1200" -> "1201" -> "1202" -> "0202"。
注意 "0000" -> "0001" -> "0002" -> "0102" -> "0202" 这样的序列是不能解锁的,
因为当拨动到 "0102" 时这个锁就会被锁定。
示例 2:

输入: deadends = ["8888"], target = "0009"
输出:1
解释:
把最后一位反向旋转一次即可 "0000" -> "0009"。
示例 3:

输入: deadends = ["8887","8889","8878","8898","8788","8988","7888","9888"], target = "8888"
输出:-1
解释:
无法旋转到目标数字且不被锁定。
示例 4:

输入: deadends = ["0000"], target = "8888"
输出:-1

提示:

死亡列表 deadends 的长度范围为 [1, 500]。
目标数字 target 不会在 deadends 之中。
每个 deadends 和 target 中的字符串的数字会在 10,000 个可能的情况 '0000' 到 '9999' 中产生。

solution1

class Solution {
    public int openLock(String[] deadends, String target) {
        //死亡之组
        Set<String> deads = new HashSet<String>();
        for (String s:deadends){ deads.add(s);}
        //遍历队列
        Deque<String> dq = new LinkedList<String>();
        //已遍历
        Set<String> visited = new HashSet<String>();
        //深度
        int depth = 0;
        dq.offer("0000");
        visited.add("0000");

        while(!dq.isEmpty()){
            int sz = dq.size();
            // 以面为单位遍历
            for (int i = 0; i < sz; i++){
                String curr = dq.poll();

                if (deads.contains(curr)) continue; 
                if (curr.equals(target)) return depth; //不能用==

                for (int j = 0; j < 4; j++){
                    String plus = plusOne(curr,j);
                    if (!visited.contains(plus)){
                        dq.offer(plus);
                        visited.add(plus);
                    }
                    String minus = minusOne(curr,j);
                    if (!visited.contains(minus)){
                        dq.offer(minus);
                        visited.add(minus);
                    }
                }
            } 
            depth++;
        }
        return -1;
    }
    // 目标转盘+1
    private String plusOne(String s,int j){
        char[] c = s.toCharArray();
        if (c[j] == '9'){
            c[j] = '0';
        }else{
            c[j]+=1;
        }
        return new String(c);
    }
    // 目标转盘-1
    private String minusOne(String s,int j){
        char[] c = s.toCharArray();
        if (c[j] == '0'){
            c[j] = '9';
        }else{
            c[j]-=1;
        }
        return new String(c);
    }

}
//运用BFS,以“0000”为根,所有转动情况为根的子节点
posted @ 2020-07-15 21:13  gg12138  阅读(166)  评论(0编辑  收藏  举报