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

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)四个方向的情况!!!

相关推荐
蓑衣客VS索尼克7 小时前
单片机中的基础外设GPIO的知识和应用—(6)
笔记·stm32·单片机·嵌入式硬件
柒十三.10 小时前
江科大51单片机笔记【10】蜂鸣器(上)
笔记·嵌入式硬件·51单片机
飞向星河12 小时前
SV学习笔记——数组、队列
笔记·学习·c#
北顾南栀倾寒12 小时前
[算法笔记]cin和getline的并用、如何区分两个数据对、C++中std::tuple类
笔记·算法
Moonnnn.13 小时前
51单片机——程序执行过程(手工汇编)
汇编·笔记·嵌入式硬件·学习·51单片机
zyhhsss13 小时前
大模型应用开发学习笔记
笔记
恋恋西风14 小时前
VTK笔记- 3D Widget类 vtkSplineWidget 样条部件
笔记
星图辛某人16 小时前
《Linux命令行和shell脚本编程大全》第四章阅读笔记
linux·运维·笔记
去看全世界的云16 小时前
【Kotlin】Kotlin基础笔记
android·java·笔记·kotlin
@卡卡-罗特16 小时前
Spring Boot笔记(上)
spring boot·笔记·后端