【网格图】【刷题笔记】【灵神题单】

1020. 飞地数量

一开始自己写的答案

python 复制代码
动态规划的核心`class Solution:
    def numEnclaves(self, grid: List[List[int]]) -> int:
        # 要求返回无法在任意次数的移动中离开网格边界的陆地单元格的数量
        # 正难则反!与边缘相接的点才可以离开边界
        # 反过来,通过边缘的点可以走到哪些位置
        # 遍历网格的四个边缘!将边缘的陆地都陆沉(=0)
        # 再统计除此之外的陆地个数!
        cnt = 0

        m = len(grid)
        n = len(grid[0])
        dirs = [[1,0], [-1,0], [0,1], [0,-1]]
        def dfs(i, j):
            # 碰网格边缘(四个方向) 或 碰水(0)时直接return,否则将当前位置陆沉=0
            if i<0 or i>=m or j<0 or j>=n or grid[i][j]==0:
                return
            grid[i][j] = 0
            for di, dj in dirs:
                i += di
                j += dj 
                dfs(i, j)
            
        # 陆沉四个边缘的陆地
        # 第一行和最后一行n  (0, j) (m-1, j)
        for j in range(n):
            # 如果grid[0][j] 和grid[m-1][j]存在 即边缘是陆地 进行陆沉
            if grid[0][j]:
                dfs(0, j)
            if grid[m-1][j]:
                dfs(m-1, j)
        for i in range(m):
            if grid[i][0] == 1:
                dfs(i, 0)
            if grid[i][n-1]==1:
                dfs(i, n-1)
        # 剩下的都是飞地 遍历数数
        for i in range(m):
            for j in range(n):
                if grid[i][j]==1:
                    cnt += 1
        return cnt
------------------------------------------------------------------------------解答错误
4 / 59 个通过的测试用例

官方题解
输入
grid =
[[0,0,0,1,1,1,0,1,0,0],[1,1,0,0,0,1,0,1,1,1],[0,0,0,1,1,1,0,1,0,0],[0,1,1,0,0,0,1,0,1,0],[0,1,1,1,1,1,0,0,1,0],[0,0,1,0,1,1,1,1,0,1],[0,1,1,0,0,0,1,1,1,1],[0,0,1,0,0,1,0,1,0,1],[1,0,1,0,1,1,0,0,0,0],[0,0,0,0,1,1,0,0,0,1]]

添加到测试用例
输出
28
预期结果
3
           
python 复制代码
class Solution:
    def numEnclaves(self, grid: List[List[int]]) -> int:
        # 要求返回无法在任意次数的移动中离开网格边界的陆地单元格的数量
        # 正难则反!与边缘相接的点才可以离开边界
        # 反过来,通过边缘的点可以走到哪些位置
        # 遍历网格的四个边缘!将边缘的陆地都陆沉(=0)
        # 再统计除此之外的陆地个数!
        cnt = 0

        m = len(grid)
        n = len(grid[0])
        dirs = [[1,0], [-1,0], [0,1], [0,-1]]
        def dfs(i, j):
            # 碰网格边缘(四个方向) 或 碰水(0)时直接return,否则将当前位置陆沉=0
            grid[i][j] = 0 
            for di, dj in dirs:
                ii = di + i
                jj = dj + j
                if 0 <= ii < m and 0 <= jj < n and grid[ii][jj]==1:
                    dfs(ii, jj)
           # if i<0 or i>=m or j<0 or j>=n or grid[i][j]==0:
            #    return
            #grid[i][j] = 0
            #for di, dj in dirs:
            # 3   i = di + i
             #   j = dj + j
              #  dfs(i, j)
            
        # 陆沉四个边缘的陆地
        # 第一行和最后一行n  (0, j) (m-1, j)
        for j in range(n):
            # 如果grid[0][j] 和grid[m-1][j]存在 即边缘是陆地 进行陆沉
            if grid[0][j]:
                dfs(0, j)
            if grid[m-1][j]:
                dfs(m-1, j)
        for i in range(m):
            if grid[i][0] == 1:
                dfs(i, 0)
            if grid[i][n-1]==1:
                dfs(i, n-1)
        # 剩下的都是飞地 遍历数数
        for i in range(m):
            for j in range(n):
                if grid[i][j]==1:
                    cnt += 1
        return cnt

            通过     但是:
 ------------------------------------------------------------------------------------------------------
class Solution:
    def numEnclaves(self, grid: List[List[int]]) -> int:
        # 要求返回无法在任意次数的移动中离开网格边界的陆地单元格的数量
        # 正难则反!与边缘相接的点才可以离开边界
        # 反过来,通过边缘的点可以走到哪些位置
        # 遍历网格的四个边缘!将边缘的陆地都陆沉(=0)
        # 再统计除此之外的陆地个数!
        cnt = 0

        m = len(grid)
        n = len(grid[0])
        dirs = [[1,0], [-1,0], [0,1], [0,-1]]
        def dfs(i, j):
            # 碰网格边缘(四个方向) 或 碰水(0)时直接return,否则将当前位置陆沉=0
            grid[i][j] = 0 
            for di, dj in dirs:
                i = di + i
                j = dj + j
                if 0 <= i < m and 0 <= j < n and grid[i][j]==1:
                    dfs(i, j)
           # if i<0 or i>=m or j<0 or j>=n or grid[i][j]==0:
            #    return
            #grid[i][j] = 0
            #for di, dj in dirs:
            # 3   i = di + i
             #   j = dj + j
              #  dfs(i, j)
            
        # 陆沉四个边缘的陆地
        # 第一行和最后一行n  (0, j) (m-1, j)
        for j in range(n):
            # 如果grid[0][j] 和grid[m-1][j]存在 即边缘是陆地 进行陆沉
            if grid[0][j]:
                dfs(0, j)
            if grid[m-1][j]:
                dfs(m-1, j)
        for i in range(m):
            if grid[i][0] == 1:
                dfs(i, 0)
            if grid[i][n-1]==1:
                dfs(i, n-1)
        # 剩下的都是飞地 遍历数数
        for i in range(m):
            for j in range(n):
                if grid[i][j]==1:
                    cnt += 1
        return cnt
 不通过!!仅仅是有没有添加新的变量名jj 和ii而已!!!我完全不懂为什么这样啊啊啊啊!

我完全不懂为什么这样啊啊啊啊!

好的,让我们来分析一下为什么仅仅是变量名的改变就导致代码不通过的情况。

在你最初通过的代码版本中,使用了 iijj 作为新的变量来表示在遍历四个方向时当前位置的坐标变化:

python 复制代码
for di, dj in dirs:
    ii = di + i
    jj = dj + j
    if 0 <= ii < m and 0 <= jj < n and grid[ii][jj] == 1:
        dfs(ii, jj)

而在不通过的代码版本中,直接复用了 ij 来表示这个变化:

python 复制代码
for di, dj in dirs:
    i = di + i
    j = dj + j
    if 0 <= i < m and 0 <= j < n and grid[i][j] == 1:
        dfs(i, j)

问题就出在复用了 ij 这两个变量上。在 dfs 函数内部,ij 原本是用来表示当前正在处理的网格位置的坐标。当你直接复用它们来计算新的位置时,就会覆盖掉原来的坐标值。

例如,假设当前 i = 2j = 3,在第一次循环遍历方向 [1, 0](即向右移动一格)时,按照正确的逻辑应该是计算出新的位置 ii = 2 + 1 = 3jj = 3 + 0 = 3,然后基于这个新位置进行后续的判断和递归操作。但在错误的代码版本中,直接将 i = di + i 变成了 i = 1 + 2 = 3,此时 i 的值就被错误地修改为新位置的横坐标了,而且后续再基于这个被修改后的 i 值去计算其他方向的新位置时,就会完全错乱,因为它已经不再是最初传入的那个表示当前位置的 i 值了。

同理,对于 j 也是如此,这样就导致在遍历周围位置并进行递归操作时,无法正确地定位到应该处理的网格位置,从而可能会遗漏一些应该处理的陆地单元格,或者错误地处理了其他位置的单元格,最终导致计算结果不正确,代码无法通过测试用例。

所以,在这种情况下,应该使用新的变量(如最初通过的代码版本中的 iijj)来临时存储计算出的新位置坐标,以保证原始的 ij 变量的值不会被意外修改,从而确保代码能够正确地遍历和处理网格中的每个位置。

!!!!原来如此!!!第二个代码一直错误的原因在于,我复用了ij!将更新后的ij跳到了下一个位置,进行了递归

但是我应该做的是仔细搜索(i, j)四个方向的情况!!!

相关推荐
遇印记3 小时前
大二java学习笔记:二维数组
java·笔记·学习
bnsarocket5 小时前
Verilog和FPGA的自学笔记6——计数器(D触发器同步+异步方案)
笔记·fpga开发·verilog·自学·硬件编程
LK_076 小时前
【Open3D】Ch.3:顶点法向量估计 | Python
开发语言·笔记·python
li星野6 小时前
打工人日报#20251011
笔记·程序人生·fpga开发·学习方法
摇滚侠6 小时前
Spring Boot 3零基础教程,yml配置文件,笔记13
spring boot·redis·笔记
QT 小鲜肉6 小时前
【个人成长笔记】在Ubuntu中的Linux系统安装 anaconda 及其相关终端命令行
linux·笔记·深度学习·学习·ubuntu·学习方法
QT 小鲜肉6 小时前
【个人成长笔记】在Ubuntu中的Linux系统安装实验室WIFI驱动安装(Driver for Linux RTL8188GU)
linux·笔记·学习·ubuntu·学习方法
急急黄豆6 小时前
MADDPG学习笔记
笔记·学习
Chloeis Syntax7 小时前
栈和队列笔记2025-10-12
java·数据结构·笔记·
QZ_orz_freedom8 小时前
学习笔记--文件上传
java·笔记·学习