【每日练习系列】—— 广度优先搜索与深度优先搜索

733. 图像渲染

在这里插入图片描述
简化问题,只从一个点分析:【初始点 / 满足条件的一点】

  • 只需要判断上下左右,是否满足要修改的条件
  • 记录每个点是否修改过,因为如果修改后的目标值与初始值相同,就可能导致陷入修改循环
  • 如果上下左右的点满足条件,那么就以该点为起始点,进入递归环节
class Solution {
    public int[][] floodFill(int[][] image, int sr, int sc, int color) {
        //获取行列
        int row = image.length;
        int col = image[0].length;
        //设置标记数组
        boolean [][] flag = new boolean[row][col];
        //初始化
        for(int i = 0; i < row; i++){
            Arrays.fill(flag[i], true);
        }
        //要改变的像素
        int old = image[sr][sc];
        //调用方法
        uColor(image, sr, sc, old, color, flag);
        //返回数组
        return image;
    }
    //对一个特定点考虑
    public void uColor(int [][] arr, int r, int c, int old, int color, boolean [][] flag){
        //将当前位置更新
        arr[r][c] = color;
        flag[r][c] = false;
                
        //对上判断
        if(r > 0 ){
            if(arr[r - 1][c] == old && flag[r - 1][c]){
                uColor(arr, r - 1, c, old, color, flag);
            }
        }
        //对下判断
        if(r < arr.length - 1){
            if(arr[r + 1][c] == old && flag[r + 1][c]){
                uColor(arr, r + 1, c, old, color, flag);
            }
        }
        //对左判断
        if(c > 0){
            if(arr[r][c - 1] == old && flag[r][c - 1]){
                uColor(arr, r, c - 1, old, color, flag);
            }
        }
        //对右判断
        if(c < arr[0].length - 1){
            if(arr[r][c + 1] == old && flag[r][c + 1]){
                uColor(arr, r, c + 1, old, color, flag);
            }
        }
    }
}

在这里插入图片描述

695. 岛屿的最大面积

在这里插入图片描述
遇到一个岛屿,就记录它的面积,与最大面积比较,更新最大面积
记录面积的方法就是,将当前为1的地方置零,然后递归它的上下左右,最后返回计数

class Solution {
    public int[][] floodFill(int[][] image, int sr, int sc, int color) {
        //获取行列
        int row = image.length;
        int col = image[0].length;
        //设置标记数组
        boolean [][] flag = new boolean[row][col];
        //初始化
        for(int i = 0; i < row; i++){
            Arrays.fill(flag[i], true);
        }
        //要改变的像素
        int old = image[sr][sc];
        //调用方法
        uColor(image, sr, sc, old, color, flag);
        //返回数组
        return image;
    }
    //对一个特定点考虑
    public void uColor(int [][] arr, int r, int c, int old, int color, boolean [][] flag){
        //将当前位置更新
        arr[r][c] = color;
        flag[r][c] = false;
        
        
        //对上判断
        if(r > 0 ){
            if(arr[r - 1][c] == old && flag[r - 1][c]){
                uColor(arr, r - 1, c, old, color, flag);
            }
        }
        //对下判断
        if(r < arr.length - 1){
            if(arr[r + 1][c] == old && flag[r + 1][c]){
                uColor(arr, r + 1, c, old, color, flag);
            }
        }
        //对左判断
        if(c > 0){
            if(arr[r][c - 1] == old && flag[r][c - 1]){
                uColor(arr, r, c - 1, old, color, flag);
            }
        }
        //对右判断
        if(c < arr[0].length - 1){
            if(arr[r][c + 1] == old && flag[r][c + 1]){
                uColor(arr, r, c + 1, old, color, flag);
            }
        }
    }
}

在这里插入图片描述

617. 合并二叉树

在这里插入图片描述
采用深度优先遍历,利用一个新的二叉树来保存结果,利用两棵树的结点来构造结果树,递归创建左右子树

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
        //存在空树
        if(root1 == null){
            return root2;
        }
        if(root2 == null){
            return root1;
        }

        //结果树
        TreeNode res = new TreeNode(root1.val + root2.val);
        //递归左子树
        res.left = mergeTrees(root1.left, root2.left);
        //递归右子树
        res.right = mergeTrees(root1.right, root2.right);
        //返回结果
        return res;

    }
}

在这里插入图片描述

116. 填充每个结点的下一个右侧结点的指针

在这里插入图片描述

/*
// Definition for a Node.
class Node {
    public int val;
    public Node left;
    public Node right;
    public Node next;

    public Node() {}
    
    public Node(int _val) {
        val = _val;
    }

    public Node(int _val, Node _left, Node _right, Node _next) {
        val = _val;
        left = _left;
        right = _right;
        next = _next;
    }
};
*/

class Solution {
    public Node connect(Node root) {
        //根结点为空
        if(root == null){
            return null;
        }

        //创建一个队列,用于记录一层的元素
        Queue<Node> queue = new LinkedList<Node>();
        queue.add(root);

        //广搜遍历二叉树
        while(!queue.isEmpty()){
            //该层元素的个数
            int size = queue.size();

            //通过循环将该层元素连接起来,并把下一层元素添加到结合中
            for(int i = 0; i < size; i++){
                //取出队首元素
                Node node = queue.poll();

                //如果当前层在队列里有剩余元素,那么就将当前元素指向队首的剩余元素
                if(i < size - 1){
                    node.next = queue.peek();
                }

                //将当前结点的子节点添加到队列中
                if(node.left != null){
                    queue.add(node.left);
                }
                if(node.right != null){
                    queue.add(node.right);
                }
            }
        }
        //返回二叉树的根结点
        return root;
    }
}

在这里插入图片描述

542. 01 矩阵

在这里插入图片描述

class Solution {
    /**
        利用队列广度优先搜索,记录所有零的位置,然后把距离为1的地方
        全部更新,然后逐步扩大范围,直至遍历完整个矩阵
     */

    //记录四个移动方向
    int [][] dirs = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
    public int[][] updateMatrix(int[][] mat) {
        //n行m列
        int n = mat.length;
        int m = mat[0].length;
        //保存结果
        int [][] res = new int[n][m];
        //记录是否遍历过
        boolean [][] seen = new boolean[n][m];
        //队列辅助广搜
        Queue<int []> queue = new LinkedList<int []>();
        //将所有零的位置添加到队列中
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++){
                if(mat[i][j] == 0){
                    queue.add(new int[]{i, j});
                    seen[i][j] = true;
                }
            }
        }

        //广度优先搜索
        while(!queue.isEmpty()){
            //取出当前的坐标
            int [] local = queue.poll();
            int i = local[0];
            int j = local[1];
            //从当前位置的四个方向开始拓展
            for(int k = 0; k < 4; k++){
                int ni = i + dirs[k][0];
                int nj = j + dirs[k][1];
                //新位置是否为没遍历过的 1
                if(ni >= 0 && ni < n && nj >=0 && nj < m && !seen[ni][nj]){
                    res[ni][nj] = res[i][j] + 1;
                    seen[ni][nj] = true;
                    queue.add(new int[]{ni, nj});
                }
            }
        }
        //返回结果
        return res;
    }
}

994. 腐烂的橘子

在这里插入图片描述

class Solution {
    /**
        与01矩阵类似,利用广度优先搜索
        记录下所有腐烂橘子的位置,每分钟向周围扩展一次,直至不能再扩展
        记录扩展次数,最后遍历格子中的所有橘子,如果存在新鲜橘子返回-1
        否则返回计数
     */
    public int orangesRotting(int[][] grid) {
        //四个方向移动
        int [][] dirs = {{-1,0},{1,0},{0,-1},{0,1}};
        //利用队列辅助遍历橘子
        Queue<int []> queue = new LinkedList<int []>();
        //数组的大小
        int n = grid.length;
        int m = grid[0].length;
        //遍历数组,将所有腐烂橘子位置记录下来
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++){
                if(grid[i][j] == 2){
                    queue.add(new int[]{i, j});
                }
            }
        }
        //计数
        int count = 0;
        int size = queue.size();
        //如果有腐烂橘子就遍历数组
        while(!queue.isEmpty()){
            //获取当前位置
            int [] place = queue.poll();
            int i = place[0], j = place[1];
            
            //向四个方向去扩展
            for(int d = 0; d < 4; d++){
                //新位置
                int ni = i + dirs[d][0];
                int nj = j + dirs[d][1];
                //判断是否为新橘子
                if(ni >= 0 && ni < n && nj >=0 && nj < m && grid[ni][nj] == 1){
                    //将新腐烂的橘子的位置记录下来
                    grid[ni][nj] = 2;
                    queue.add(new int[]{ni, nj});
                }
            }
            //这一分钟是当前这轮所有腐烂的橘子都扩展完
            if(--size == 0){
                count++;
                //下轮扩展的次数
                size = queue.size();
            }
            
        }
        //遍历数组,查看是否所有橘子都腐烂了
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++){
                if(grid[i][j] == 1){
                    return -1;
                }
            }
        }
        //都腐烂了或者都是新鲜的【因为最后有一次无效扩展】
        return count == 0 ? 0 : count - 1;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bow.贾斯汀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值