LeetCode 733. 图像渲染 | Python

733. 图像渲染


题目来源:力扣(LeetCode)https://leetcode-cn.com/problems/flood-fill

题目


有一幅以二维整数数组表示的图画,每一个整数表示该图画的像素值大小,数值在 0 到 65535 之间。

给你一个坐标 (sr, sc) 表示图像渲染开始的像素值(行 ,列)和一个新的颜色值 newColor,让你重新上色这幅图像。

为了完成上色工作,从初始坐标开始,记录初始坐标的上下左右四个方向上像素值与初始坐标相同的相连像素点,接着再记录这四个方向上符合条件的像素点与他们对应四个方向上像素值与初始坐标相同的相连像素点,……,重复该过程。将所有有记录的像素点的颜色值改为新的颜色值。

最后返回经过上色渲染后的图像。

示例 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,
因为它不是在上下左右四个方向上与初始点相连的像素点。

注意:

  • image 和 image[0] 的长度在范围 [1, 50] 内。
  • 给出的初始点将满足 0 <= sr < image.length 和 0 <= sc < image[0].length。
  • image[i][j] 和 newColor 表示的颜色值在范围 [0, 65535]内。

解题思路


思路:DFS、BFS

先审题,题目要求是将某些符合条件的坐标点进行重新上色。这里这些坐标点符合的定义为:直接或间接相邻的与起始坐标点颜色相同的部分。

在题目中,明确说了从给定的初始坐标开始,往坐标点四个方位进行扩散,标记与初始坐标点颜色相同的坐标,然后以这些标记的点继续扩散,重复直至结束,将所有标记的点都重新上色。

那么,我们这里采用深度优先搜索和广度优先搜索的形式来解决这个问题。

深度优先搜索(DFS)

首先,先看深度优先搜索如何处理。具体的做法如下:

  • 首先从给定的初始坐标点开始向四个方位扩散,进行遍历;
  • 每搜索一个坐标,确定是否与初始坐标点颜色相同。如果相同,那么重新上色,防止重新搜索陷入死循环;如果不同,不处理。
  • 重复直至所有符合条件的点都重新上色,返回重新上色后的图像。

这里有个需要注意的地方,进行扩散的时候,按照上面的做法,会将初始坐标点进行重新上色。这个时候颜色的变化会影响后续。所以开始前用一个变量存储初始坐标点的颜色。
还有,给定的初始坐标点颜色,可能与新给定的颜色相同,这样直接调用会先入死循环。这也是测试用例没通过注意到的。┑( ̄Д  ̄)┍

具体的代码见【代码实现 # 深度优先搜索】

广度优先搜索(BFS)

在这里,我们同样可以使用广度优先搜索的思路来解决这个问题。下面看使用此方法的思路:

  • 声明辅助队列,从初始坐标点开始,先将初始坐标点入队;
  • 出队,开始搜索,当遇到与初始坐标点颜色相同的点时,入队,同时将重新上色;
  • 循环直至队列为空,返回重新上色后的图像。

同样注意初始坐标点颜色可能会被覆盖的问题。

具体的代码见【代码实现 # 广度优先搜索】

代码实现


# 深度优先搜索
class Solution:
    def floodFill(self, image: List[List[int]], sr: int, sc: int, newColor: int) -> List[List[int]]:
        # 先存储初始坐标点颜色
        init_color = image[sr][sc]
        # 边界
        m = len(image)
        n = len(image[0])
        # 四个方位
        directions = [(0, 1), (0, -1), (-1, 0),(1, 0)]

        def dfs(x, y):
            """进行深度优先搜索
            Args:
                x: 像素值(行)
                y: 像素值(列)
            """
            if image[x][y] == init_color:
                # 如果遇到与初始坐标点颜色相同的点,重新上色,开始扩散
                image[x][y] = newColor
                for dx, dy in directions:
                    nx = x + dx
                    ny = y + dy
                    # 限定边界
                    if 0 <= nx < m and 0 <= ny < n and image[nx][ny] == init_color:
                        dfs(nx, ny)

        # 注意:
        # 有可能一开始给定的初始坐标点的颜色与后面给定的新颜色是相同的
        # 直接调用会先入死循环,直至超出递归深度
        if init_color != newColor:
            dfs(sr, sc)

        return image

# 广度优先搜索
class Solution:
    def floodFill(self, image: List[List[int]], sr: int, sc: int, newColor: int) -> List[List[int]]:
        # 先存储初始坐标点颜色
        init_color = image[sr][sc]
        # 边界
        m = len(image)
        n = len(image[0])
        # 四个方位
        directions = [(0, 1), (0, -1), (-1, 0),(1, 0)]

        def bfs(sr, sc):
            """进行深度优先搜索
            Args:
                sr: 像素值(行)
                sc: 像素值(列)
            """
            # 声明辅助队列
            from collections import deque
            queue = deque()
            # 入队
            queue.append([sr, sc])
            # 重新上色
            image[sr][sc] = newColor
            # 出队,开始搜索
            while queue:
                x, y = queue.popleft()
                for dx, dy in directions:
                    nx = x + dx
                    ny = y + dy
                    if 0 <= nx < m and 0 <= ny < n and image[nx][ny] == init_color:
                        # 当遇到与初始坐标点颜色相同的,入队,并重新上色
                        queue.append([nx, ny])
                        image[nx][ny] = newColor

        if init_color != newColor:
            bfs(sr, sc)

        return image

实现结果


实现结果 | 深度优先搜索

实现结果 | 广度优先搜索

欢迎关注


公众号 【书所集录

posted @ 2020-08-16 18:44  "大梦三千秋  阅读(260)  评论(0编辑  收藏  举报