美文网首页
1034. 边框着色(Python)

1034. 边框着色(Python)

作者: 玖月晴 | 来源:发表于2021-05-31 14:12 被阅读0次

    难度:★★★☆☆
    类型:数组
    方法:深度优先搜索,宽度优先搜索

    题目

    力扣链接请移步本题传送门
    更多力扣中等题的解决方案请移步力扣中等题目录

    给出一个二维整数网格 grid,网格中的每个值表示该位置处的网格块的颜色。

    只有当两个网格块的颜色相同,而且在四个方向中任意一个方向上相邻时,它们属于同一连通分量。

    连通分量的边界是指连通分量中的所有与不在分量中的正方形相邻(四个方向上)的所有正方形,或者在网格的边界上(第一行/列或最后一行/列)的所有正方形。

    给出位于 (r0, c0) 的网格块和颜色 color,使用指定颜色 color 为所给网格块的连通分量的边界进行着色,并返回最终的网格 grid 。

    示例 1:

    输入:grid = [[1,1],[1,2]], r0 = 0, c0 = 0, color = 3
    输出:[[3, 3], [3, 2]]

    示例 2:

    输入:grid = [[1,2,2],[2,3,2]], r0 = 0, c0 = 1, color = 3
    输出:[[1, 3, 3], [2, 3, 3]]

    示例 3:

    输入:grid = [[1,1,1],[1,1,1],[1,1,1]], r0 = 1, c0 = 1, color = 2
    输出:[[2, 2, 2], [2, 1, 2], [2, 2, 2]]

    提示:

    1 <= grid.length <= 50
    1 <= grid[0].length <= 50
    1 <= grid[i][j] <= 1000
    0 <= r0 < grid.length
    0 <= c0 < grid[0].length
    1 <= color <= 1000

    解答

    画图软件读者应该熟悉吧,可以尝试里面的颜料桶操作,把一个连通域换成另一个颜色,但是如果本题仅仅是实现这个功能,就简单了,本题不仅需要找到连通域,而且还要分类联通域中每个点是否属于边界点,仅把边界点进行着色。

    我们给出一些定义,把选定点 (r0, c0) 作为起始点,将该点所在联通域作为选定区域,该区域中边界上的点作是着色点。

    着色点需要满足以下任意一个条件:
    第一,该点在选定区域内,并且该点位于整个方格的边框上;
    第二,该点在选定区域内,并且该点周围四个点中,有任意一个点的颜色与该点不同。

    一个简单的做法是,我们通过深度优先搜索得到选定区域中的每个点,然后根据上述原则选出来选定区域中的边界点,并对其进行着色。

    class Solution:
        def colorBorder(self, grid, r0, c0, color):
            self.grid = [[c for c in row] for row in grid]
            self.rows = len(grid)
            self.columns = len(grid[0])
            self.area = [[False for _ in range(self.columns)] for _ in range(self.rows)]
            self.prev_color = grid[r0][c0]
            self.new_color = color
    
            def is_border(r, c):
                if r == 0 or r == self.rows - 1:
                    return True
                if c == 0 or c == self.columns - 1:
                    return True
                return not all(grid[r][c] == grid[nr][nc] for nr, nc in get_neighbors(r, c))
    
            def get_neighbors(r, c):
                for nr, nc in [(r + 1, c), (r - 1, c), (r, c + 1), (r, c - 1)]:
                    if 0 <= nr < self.rows and 0 <= nc < self.columns:
                        yield nr, nc
    
            def dfs(r, c):
                if not self.area[r][c] and self.grid[r][c] == self.prev_color:
                    self.area[r][c] = True
                    for nr, nc in get_neighbors(r, c):
                        dfs(nr, nc)
    
            def color_grid():
                for r in range(self.rows):
                    for c in range(self.columns):
                        if self.area[r][c] and is_border(r, c):
                            self.grid[r][c] = self.new_color
    
            dfs(r0, c0)
            color_grid()
            return self.grid
    
    
    s = Solution()
    grid = [[1,2,2],
            [2,3,2]]
    print(s.colorBorder(grid, 0, 1, 3))
    
    grid = [[1,1,1],
            [1,1,1],
            [1,1,1]]
    print(s.colorBorder(grid, 1, 1, 2))
    

    为了便于理解,以上代码都写成了函数块的方式,当然,可以在代码上做一些简化,尤其要注意逻辑上的判断条件:

    from typing import List
    class Solution:
        def colorBorder(self, grid: List[List[int]], r0: int, c0: int, color: int) -> List[List[int]]:
            if not grid:
                return []
            pos = [(-1, 0), (1, 0), (0, -1), (0, 1)]
            m, n = len(grid), len(grid[0])
            visited = {(r0, c0)}
            target = grid[r0][c0]
    
            def dfs(r, c):
                for dr, dc in pos:
                    nr = r + dr
                    nc = c + dc
                    if 0 <= nr < m and 0 <= nc < n:
                        if (nr, nc) not in visited:
                            if grid[nr][nc] == target:
                                visited.add((nr, nc))
                                dfs(nr, nc)
                            else:
                                grid[r][c] = color
                    else:
                        grid[r][c] = color
    
            dfs(r0, c0)
            return grid
    

    或者使用宽度优先搜索算法实现,算法流程和上面是一样的,仅仅把递归换成了队列:

    from typing import List
    class Solution:
        def colorBorder(self, grid: List[List[int]], r0: int, c0: int, color: int) -> List[List[int]]:
            if not grid:
                return []
            pos = [(-1, 0), (1, 0), (0, -1), (0, 1)]
            rows, columns = len(grid), len(grid[0])
            queue = [(r0, c0)]
            visited = {(r0, c0)}
            target = grid[r0][c0]
    
            while queue:
                r, c = queue.pop(0)
                for dr, dc in pos:
                    nr = r + dr
                    nc = c + dc
                    if 0 <= nr < rows and 0 <= nc < columns:
                        if (nr, nc) not in visited:
                            if grid[nr][nc] == target:
                                visited.add((nr, nc))
                                queue.append((nr, nc))
                            else:
                                grid[r][c] = color
                    else:
                        grid[r][c] = color
    
            return grid
    

    如有疑问或建议,欢迎评论区留言~

    有关更多力扣中等题的python解决方案,请移步力扣中等题解析

    相关文章

      网友评论

          本文标题:1034. 边框着色(Python)

          本文链接:https://www.haomeiwen.com/subject/bhttkltx.html