从两道题入门广度搜索

733 . 图像渲染

示例 1:
输入:
image = [[1,1,1],[1,1,0],[1,0,1]]
sr = 1, sc = 1, newColor = 2
输出: [[2,2,2],[2,2,0],[2,0,1]]
解析:
在图像的正中间,(坐标(sr,sc)=(1,1)),
在路径上所有符合条件的像素点的颜色都被更改成2。
注意,右下角的像素没有更改为2,
因为它不是在上下左右四个方向上与初始点相连的像素点。

为了直观查看,将样例二维数组铺开:
1 1 1
1 1 0
1 0 1

  • 此时我们从最中心的1入手

  • 先将它的值改变为newColor

  • 然后,再向四周遍历!
    思想很简单,但我们知道,遍历不可能是永不停歇的,必须找到条件对遍历加以限制,否则代码将陷入死循环。

  • 首先想到的,是下标不能越界,也就是超出二维数组的范围

  • 然后,由于四周遍历的特性,导致上下之间的数会重复遍历,也就是我刚刚上去,一会又会下来,如果不能解决这个问题,代码会进入死循环。

  • 还有一个条件,是题意告诉我们,我们只修改数字相同的一片数组,否则,程序执行完后,整个数组的值都会被涂抹成newColor。所以我们知道,值是否与最开始的image[sr][sc](下面把它称作oldColor)相等,也是一个边界条件。(到这里,这题已经基本解决了

  • 还有最后一个问题,如果newColor和oldColor相等,那会导致上一个条件失效,因为即使当前的值与oldColor相等,它也有可能是被遍历过的!而这会导致相邻位置来回反复遍历,造成死循环。这种情况有两种做法

    • 判断当前值和newColor是否相等,有效防止反复遍历的,思想是既然你已经改成了newColor,说明你被遍历过了,那自然不用遍历直接退出。
      • 在newColor和oldColor不相等的时候,其实用不到它,因为如果等于oldColor,自然就不等于newColor了,这是一句废话。
      • 而如果newColor和oldColor相等,第一步也会导致直接返回,不管你登不等于,if都会成立if(arr[sr][sc] == newColor||arr[sr][sc] != oldColor) return ;
    • 也可以直接在最开始就判断newColor是否相等,相等直接返回原数组,因为没必要改了。if(image[sr][sc] == newColor) return image;

到这里这道题就结束了,一道看似很简单的简单题,却有三个边界条件,还是值得好好琢磨的,广度搜索建立在递归的基础上,和递归一样,必须把边界条件控制好才行。

public int[][] floodFill(int[][] image, int sr, int sc, int newColor) {
     
        dfs(image,sr,sc,image[sr][sc],newColor);
        return image;
    }
    public void dfs(int[][] arr, int sr, int sc,int oldColor, int newColor)
    {
     
        if(sr>=arr.length||sr<0||sc>=arr[0].length||sc<0
        ||arr[sr][sc] == newColor||arr[sr][sc] != oldColor)
            return ;   
        arr[sr][sc] = newColor;
        dfs(arr,sr+1,sc,oldColor,newColor);
        dfs(arr,sr-1,sc,oldColor,newColor);
        dfs(arr,sr,sc+1,oldColor,newColor);
        dfs(arr,sr,sc-1,oldColor,newColor);
    }

200.岛屿数量

这道题和刚才的题很像,很像,一样是“感染”周围的元素,把它们变成和自己一样的数字,唯一的区别是多了一个遍历累加的操作。

  • 连在一片的“1”视为一个岛,那么在遍历的时候,碰到第一个1后,就执行“感染”函数,把相连的其他“1”置为“2”(是不是和刚才一毛一样)。这样一来,之后再遍历到它们的时候它们也不是1,没法看做是岛了~
  • 这题不像上题一样需要那么多边界条件,因为数据中只有0和1,我们把1改成2,不存在要改的数和原来数一样的情况。
 public static void infect(char[][] grid,int i,int j,int x,int y) {
     
            if (i < 0 || i >= x || j < 0 || j >= y ||grid[i][j] != '1')
                return;
            grid[i][j] = '2';
            infect(grid,i+1,j,x,y);
            infect(grid,i-1,j,x,y);
            infect(grid,i,j+1,x,y);
            infect(grid,i,j-1,x,y);
        }
        public static int numIslands(char[][] gird) {
     
            if (gird == null || gird.length == 0)
                return 0;
            int x = gird.length;
            int y = gird[0].length;
            int res = 0;
            for (int i = 0;i < x;i++ )
            {
     
                for (int j = 0;j < y;j++ )
                {
     
                    if (gird[i][j] == '1')
                    {
     
                        res++;
                        infect(gird,i,j,x,y);
                    }
                }
           
        }
      return res; 
        } 

你可能感兴趣的:(算法,LeetCode,广度搜索)