leetcode刷题日记-边界着色

  • 题目描述
  • 给你一个大小为 m x n 的整数矩阵 grid ,表示一个网格。另给你三个整数 row、col 和 color 。网格中的每个值表示该位置处的网格块的颜色。
    当两个网格块的颜色相同,而且在四个方向中任意一个方向上相邻时,它们属于同一 连通分量 。
    连通分量的边界 是指连通分量中的所有与不在分量中的网格块相邻(四个方向上)的所有网格块,或者在网格的边界上(第一行/列或最后一行/列)的所有网格块。
    请你使用指定颜色 color 为所有包含网格块 grid[row][col] 的 连通分量的边界 进行着色,并返回最终的网格 grid 。

  • 示例:
  • 输入:grid = [[1,1],[1,2]], row = 0, col = 0, color = 3
    输出:[[3,3],[3,2]]
    输入:grid = [[1,2,2],[2,3,2]], row = 0, col = 1, color = 3
    输出:[[1,3,3],[2,3,3]]
    输入:grid = [[1,1,1],[1,1,1],[1,1,1]], row = 1, col = 1, color = 2
    输出:[[2,2,2],[2,1,2],[2,2,2]]

  • 解析:这是一个看上去很复杂,实际上很简单,代码写起来很复杂的题目(哈哈哈,经典说了等于没说),说他看看上去很复杂是因为涉及到连通分量的边界问题,一个是处于连通分量中心(四个方向上均为同样的连通分量),一个是处于数组边界,所以不是几行代码就能搞定的,说他实际上很简单,是因为这个题目就考了一个深度优先遍历(当然,广度优先遍历也行),说他代码写起来很复杂,是因为这个题目有很多优化的空间,本例中我用了两个嵌套for循环来完成连通分量和其边界赋值,就很Low。
  • 代码如下
class Solution:
    def colorBorder(self, grid: List[List[int]], row: int, col: int, color: int) -> List[List[int]]:
        """
        使用指定颜色 color 为所有包含网格块 grid[row][col] 的 连通分量的边界 进行着色,并返回最终的网格 grid 
        >>>self.colorBorder([[1,1],[1,2]], 0, 0, 3)
        >>>[[3,3],[3,2]]
        """
        start = grid[row][col]
        start_list = []
        #深度优先遍历找到所有连通分量,并设置为0,因为color的取值范围是大于1的
        def dfs(grid, row, col):
            if grid[row][col] != start:
                return
            grid[row][col] = 0
            for row1, col1 in [(row, col-1), (row, col+1), (row-1, col),(row+1, col)]:
                if 0<=row1<len(grid) and 0<=col1<len(grid[0]):
                    dfs(grid, row1, col1)
        dfs(grid, row, col)
        #找到非连通分量边界的连通分量,保存索引
        for i in range(len(grid)):
            for j in range(len(grid[0])):
                if grid[i][j] == 0:
                    if 0<i<len(grid)-1 and 0<j<len(grid[0])-1:
                        if self.helpFunc(grid, i, j):
                            start_list.append((i, j))
		#为连通分量和连通分量边界分别赋值
        for i in range(len(grid)):
            for j in range(len(grid[0])):
                if grid[i][j] == 0:
                    if (i, j) in start_list:
                        grid[i][j] = start
                    else:
                        grid[i][j] = color
        return grid
        
    def helpFunc(self, grid, i , j):
        """
        一个help function,判断一个点的四个方向上的四个点是否全为0
        >>>self.helpFunc([[0, 0 ,0], [0, 0 ,0], [0, 0 ,0]], 1, 1)
        >>>True
        """
        for ni, nj in [(i, j-1), (i, j+1), (i-1, j),(i+1, j)]:
            if grid[ni][nj] != 0:
                return False
        return True

  这里提供两个优化思路,代码我就不写了。

  • 优化的重点就是两个嵌套for循环那里,优化思路就是把两个嵌套for循环缩减为一个嵌套for循环,这里有两种方式,第一种是在第一层嵌套for循环里面就完成赋值操作,这需要重写一下help function,在主方法里面进行赋值的时候记录所有值为0的坐标,将这个坐标数组作为参数传入help function,比如叫help_list:,这样就可以即便当前值改变了,也不影响后续的非连通分量边界分量的判断,这样help function的判断语句就变成了if grid[ni][nj] != 0 and (i, j) not in help_list
  • 第二种优化思路是在深度优先遍历的时候除了对原数组进行操作外,同时记录下所有连通分量的坐标位置,比如叫conn_list,然后对索引进行遍历赋值,这样的效率会更高,同样的这里也需要重写help_function,需要当前位置四个方向的所有坐标均在conn_list中,否则返回False,这种优化思路明显更好。测试时间从48ms变成了24ms。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lemon_tttea

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值