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

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

相关推荐
愚润求学9 分钟前
【Linux】基础 IO(一)
linux·运维·服务器·开发语言·c++·笔记
Wallace Zhang18 分钟前
STM32F103_LL库+寄存器学习笔记22 - 基础定时器TIM实现1ms周期回调
笔记·stm32·学习
大白的编程日记.41 分钟前
【Linux学习笔记】理解一切皆文件实现原理和文件缓冲区
linux·笔记·学习
孞㐑¥42 分钟前
Linux之进程控制
linux·开发语言·c++·经验分享·笔记
Alessio Micheli1 小时前
奇怪的公式
笔记·线性代数
愚润求学1 小时前
【Linux】简单设计libc库
linux·运维·开发语言·c++·笔记
chennalC#c.h.JA Ptho1 小时前
Bodhi linux 系统详解
linux·经验分享·笔记·系统架构·系统安全
zhuziheniaoer2 小时前
rust-candle学习笔记11-实现一个简单的自注意力
笔记·学习·自然语言处理·rust
LAM LAB2 小时前
【WIN】笔记本电脑忘记密码解决办法/笔记本电脑重装系统笔记/bitlocker忘记密码的解决办法
笔记·电脑
lwewan3 小时前
26考研——中央处理器_指令执行过程(5)
笔记·考研