算法入门 05深度优先搜索(简单 - 第一题)LeetCode 733

Posted 英雄哪里出来

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法入门 05深度优先搜索(简单 - 第一题)LeetCode 733相关的知识,希望对你有一定的参考价值。

🙉饭不食,水不饮,题必须刷🙉

还不会C语言,和我一起打卡!
🌞《光天化日学C语言》🌞

LeetCode 太难?上简单题!
🧡《C语言入门100例》🧡

LeetCode 太简单?大神盘他!
🌌《夜深人静写算法》🌌

一、题目

1、题目描述

  有一幅以二维整数数组表示的图画,每一个整数表示该图画的像素值大小,数值在 0 到 65535 之间。给你一个坐标(sr, sc)表示图像渲染开始的像素值(行 ,列)和一个新的颜色值 newColor,让你重新上色这幅图像。为了完成上色工作,从初始坐标开始,记录初始坐标的上下左右四个方向上像素值与初始坐标相同的相连像素点,接着再记录这四个方向上符合条件的像素点与他们对应四个方向上像素值与初始坐标相同的相连像素点,……,重复该过程。将所有有记录的像素点的颜色值改为新的颜色值。最后返回经过上色渲染后的图像。
  样例1: [ [ 1 , 0 , 1 ] , [ 1 , 1 , 0 ] , [ 0 , 0 , 1 ] , [ 0 , 0 , 0 ] , [ 1 , 1 , 1 ] ] [[1,0,1],[1,1,0],[0,0,1],[0,0,0],[1,1,1]] [[1,0,1],[1,1,0],[0,0,1],[0,0,0],[1,1,1]] s r = 1 , s c = 1 , n e w C o l o r = 2 sr = 1, sc = 1, newColor = 2 sr=1,sc=1,newColor=2,输出 [ [ 2 , 0 , 1 ] , [ 2 , 2 , 0 ] , [ 0 , 0 , 1 ] , [ 0 , 0 , 0 ] , [ 1 , 1 , 1 ] ] [[2,0,1],[2,2,0],[0,0,1],[0,0,0],[1,1,1]] [[2,0,1],[2,2,0],[0,0,1],[0,0,0],[1,1,1]]

2、基础框架

  • c++ 版本给出的基础框架代码如下,定义一个函数floodFill,函数的参数是一个vector的嵌套,代表的是一个二维数组;
  • vector<vector<int>>可以理解成vector<T>,其中T代表vector的元素,并且这个元素是另一个vector<int>。当然,可以嵌套的实现三维数组,甚至更高维的数组。
  • sr, sc分别表示位置,下标从 0 开始,newColor则代表对应位置的连通块都会被染成的新的颜色;
class Solution {
public:
    vector<vector<int>> floodFill(vector<vector<int>>& grid, int sr, int sc, int newColor) {
    }
};

3、原题链接

LeetCode 733. 图像渲染

二、解题报告

1、思路分析

  • g r i d grid grid 中的每个 1 抽象成一个节点,且都有一个唯一编号。两个水平或者垂直方向相邻且都为 1,则在这两个节点之间连接一条无向边。举个例子:
  • [ 1 0 0 1 1 1 0 1 0 1 1 1 ] \\left[ \\begin{matrix} 1 & 0 & 0 & 1 \\\\ 1 & 1 & 0 & 1 \\\\ 0 & 1 & 1 & 1 \\end{matrix} \\right] 110011001111
  • 先将每个 1 的位置都分配一个编号,假设行号为 i i i,列号为 j j j,则它的编号就是 i × 4 + j i \\times 4 + j i×4+j,其中 4 4 4 代表总共有多少列。如下:
  • [ 0 E E 3 4 5 E 7 E 9 10 11 ] \\left[ \\begin{matrix} 0 & E & E & 3 \\\\ 4 & 5 & E & 7 \\\\ E & 9 & 10 & 11 \\end{matrix} \\right] 04EE59EE103711
  • E E E 的含义是 Empty 的意思,可以用一个额外的编号(不和其它现有编号冲突)表示,比如 -1。
  • 所以,它其实应该是这样一个图:
  • 这样,我们就可以转换成用深度优先搜索来求连通块问题了。
  • 最后遍历一次哈希数组,标记为 1 的将设置上给定的颜色值即可。
  • 关于深度优先搜索的更深入内容,可以参考这篇文章:夜深人静写算法(一)- 搜索入门

2、时间复杂度

  • 由于有哈希数组在,所以 g r i d grid grid 的每个元素最多被访问一次,如果长为 n n n 宽为 m m m g r i d grid grid,时间复杂度为 O ( n m ) O(nm) O(nm)

3、代码详解

const int dir[4][2] = { {0, 1}, {0, -1}, {1, 0}, {-1, 0} };           // (1)
int bHash[100][100];                                                  // (2)
int n, m;                                                             // (3)

class Solution {
public:
    void dfs(vector<vector<int>>& grid, int x, int y, int color) {
        if(x < 0 || y < 0 || x >= n || y >= m) {
            return ;                                                  // (4)
        }
        if(color != grid[x][y]) {
            return ;                                                  // (5)
        }

        if(bHash[x][y]) {
            return;                                                   // (6)
        }  
        bHash[x][y] = 1;                                              // (7)

        for(int i = 0; i < 4; ++i) {
            dfs(grid, x + dir[i][0], y + dir[i][1], color);           // (8)
        }
    }
    vector<vector<int>> floodFill(vector<vector<int>>& grid, int sr, int sc, int newColor) {
        n = grid.size();
        m = grid[0].size();
        memset(bHash, 0, sizeof(bHash));
        dfs(grid, sr, sc, grid[sr][sc]);                            // (9)
        for(int i = 0; i < n; ++i) {
            for(int j = 0; j < m; ++j) {
                if(bHash[i][j]) {                                     // (10)
                    grid[i][j] = newColor;
                }
            }
        }
        return grid;
    }
};


  • ( 1 ) (1) (1) 代表四个方向的全局向量;
  • ( 2 ) (2) (2) 二维的哈希数组,用来标记一个位置有没有被访问过;
  • ( 3 ) (3) (3) 全局缓存 g r i d grid grid 的宽 和 高;
  • ( 4 ) (4) (4) 遇到边界,终止本次搜索;
  • ( 5 ) (5) (5) 遇到颜色不一样的相邻块,终止本次搜索;
  • ( 6 ) (6) (6) 遇到已经搜索过的块,终止本次搜索;
  • ( 7 ) (7) (7) 标记当前搜索块;
  • ( 8 ) (8) (8) 从四个相邻的位置开始搜索;
  • ( 9 ) (9) (9) 从一个其实位置sr,sc往四个方向进行搜索和当前位置相同颜色的块,并且标记对应位置的bHash数组值为 1;
  • ( 10 ) (10) (10) 将所有bHash[i][j] == 1的位置的 grid[i][j]设置为新的颜色;

三、本题小知识

利用深度优先搜索,可以用来求图的连通块问题。


以上是关于算法入门 05深度优先搜索(简单 - 第一题)LeetCode 733的主要内容,如果未能解决你的问题,请参考以下文章

算法入门广度优先搜索(简单 - 第一题)LeetCode 542

算法入门广度优先搜索(中等 - 第一题)LeetCode 994

算法入门深度优先搜索(简单 - 第二题)LeetCode 617

LeetCode每日一题——851. 喧闹和富有

岛屿的数量(深度优先搜索算法)

⭐算法入门⭐《深度优先搜索》简单02 —— LeetCode 617. 合并二叉树