LeetCode:733. 图像渲染(java版)——BFS是渣男/女,DFS是方知有

题外话:看完题目,是不是一头雾水。有疑问就对了,不知道出题者的语文老师看了有啥感想。

题目意思其实很简单,就是给你一个初始坐标点(sr,sc),找和该点附近像素值相同的坐标,而这附近的定义就是上下左右,不包括斜对角;然后将这些像素值替换为新的像素值newColor。

虽然题目是easy,但是对我而言不是easy༼༎ຶᴗ༎ຶ༽(so sad...

话不多说,直接看解题方法吧!

方法1:广度优先搜索BFS(Broad First Search)

我们从给定的起点开始,进行广度优先搜索。每次搜索到一个方格时,如果其与初始位置的方格颜色相同,就将该方格加入队列,并将该方格的颜色更新,以防止重复入队。

注意:因为初始位置的颜色会被修改,所以我们需要保存初始位置的颜色,以便于之后的更新操作。

我愿称广度优先搜索为鱼塘大法!queue是鱼塘,先广撒网(for);再判断是非(if)

虽为鱼塘大法,但是我觉得好用且易理解,reject歧视算法(假正经~

class Solution {
    public int[][] floodFill(int[][] image, int sr, int sc, int newColor) {
        // 题意:油漆桶工具
        // 1. 广度优先搜索——queue
        int[] dx={0,1,0,-1};
        int[] dy={1,0,-1,0};    // 两个数组结合起来看就是右,下,左,上
        int m=image.length; // row number
        int n=image[0].length;  // column numer
        Queue<int[]> queue=new LinkedList<>();
        int oldColor=image[sr][sc];
        if(oldColor==newColor)  return image;   //特殊情况
        queue.offer(new int[]{sr, sc});
        image[sr][sc]=newColor;
        while(!queue.isEmpty()){    // 广度遍历符合条件的像素点坐
            int[] xy=queue.poll();
            int x=xy[0],y=xy[1];
            for(int i=0;i<4;i++){    // 先广撒网,再判断是非
                int mx=x+dx[i],my=y+dy[i];
                if(mx>=0 && mx<m && my>=0 && my<n && image[mx][my]==oldColor){    // 判断是非
                    image[mx][my]=newColor;
                    queue.offer(new int[]{mx,my});
                }
            }
        }
        return image;
    }
}

 方法2:假 深度优先搜索

为什么是假?因为本质上还是有广度优先搜索的影子,没有按照一个方向走到底,只是将存储搜索过的坐标数据结构从队列queue变成栈stack。其实本质还是跟方法1一样的。

class Solution {
    public int[][] floodFill(int[][] image, int sr, int sc, int newColor) {     
        // 2. 假深度优先搜索——stack
        int[] dx={0,1,0,-1};
        int[] dy={1,0,-1,0};    // 两个数组结合起来看就是右,下,左,上
        int m=image.length; // row number
        int n=image[0].length;  // column numer
        Deque<int[]> stack=new LinkedList<>();
        int oldColor=image[sr][sc];
        if(oldColor==newColor)  return image;
        stack.push(new  int[]{sr,sc});
        image[sr][sc]=newColor;
        while(!stack.isEmpty()){    // 广度遍历符合条件的像素点坐
            int[] xy=stack.pop();
            int x=xy[0],y=xy[1];
            for(int i=0;i<4;i++){
                int mx=x+dx[i],my=y+dy[i];
                if(mx>=0 && mx<m && my>=0 && my<n && image[mx][my]==oldColor){
                    image[mx][my]=newColor;
                    stack.push(new int[]{mx,my});
                }
            }
        }
        return image;
    }
}

方法3:深度优先搜索DFS(Deep First Search)——递归

我们从给定的起点开始,进行深度优先搜索。每次搜索到一个方格时,如果其与初始位置的方格颜色相同,就将该方格的颜色更新,以防止重复搜索;如果不相同,则进行回溯。

注意:因为初始位置的颜色会被修改,所以我们需要保存初始位置的颜色,以便于之后的更新操作。

“斯人若彩虹,遇上方知有”

​​​​​​​深度优先搜索是彩虹:先排除不合适的(直接return);再选择合适的(if),如果再不合适就换(for)

DFS是心上人,可遇不可求,想想就好~~

class Solution {
    int[] dx={0,1,0,-1};
    int[] dy={1,0,-1,0};    // 两个数组结合起来看就是右,下,左,上
    public  int[][] floodFill(int[][] image, int sr, int sc, int newColor) {
        // 3.深度优先——递归
        int oldColor=image[sr][sc];
        if(newColor!=oldColor)  dfs(image,sr,sc,newColor,oldColor);
        return image;
    }

    public  void dfs(int[][] image, int x, int y, int newColor, int oldColor){
        int m=image.length; // row number
        int n=image[0].length;  // column number
        if(!(x>=0 && x<m && y>=0 && y<n))   return;    // 先排除不合适的
        if(image[x][y]!=oldColor)   return;
        if(image[x][y]==oldColor){    // 先判断是非,不合适再换
            image[x][y]=newColor;
            for (int i=0;i<4;i++){    // 换
                int mx=x+dx[i],my=y+dy[i];
                dfs(image,mx,my,newColor,oldColor);
            }
        }
    }
}

参考:

力扣

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
给定一个整数数组 nums 和一个目标值 target,要求在数组中找出两个数的和等于目标值,并返回这两个数的索引。 思路1:暴力法 最简单的思路是使用两层循环遍历数组的所有组合,判断两个数的和是否等于目标值。如果等于目标值,则返回这两个数的索引。 此方法的时间复杂度为O(n^2),空间复杂度为O(1)。 思路2:哈希表 为了优化时间复杂度,可以使用哈希表来存储数组中的元素和对应的索引。遍历数组,对于每个元素nums[i],我们可以通过计算target - nums[i]的值,查找哈希表中是否存在这个差值。 如果存在,则说明找到了两个数的和等于目标值,返回它们的索引。如果不存在,将当前元素nums[i]和它的索引存入哈希表中。 此方法的时间复杂度为O(n),空间复杂度为O(n)。 思路3:双指针 如果数组已经排序,可以使用双指针的方法来求解。假设数组从小到大排序,定义左指针left指向数组的第一个元素,右指针right指向数组的最后一个元素。 如果当前两个指针指向的数的和等于目标值,则返回它们的索引。如果和小于目标值,则将左指针右移一位,使得和增大;如果和大于目标值,则将右指针左移一位,使得和减小。 继续移动指针,直到找到两个数的和等于目标值或者左指针超过了右指针。 此方法的时间复杂度为O(nlogn),空间复杂度为O(1)。 以上三种方法都可以解决问题,选择合适的方法取决于具体的应用场景和要求。如果数组规模较小并且不需要考虑额外的空间使用,则暴力法是最简单的方法。如果数组较大或者需要优化时间复杂度,则哈希表或双指针方法更合适。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值