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

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

相关推荐
rellvera2 小时前
【强化学习的数学原理】第03课-贝尔曼最优公式-笔记
笔记·机器学习
吃着火锅x唱着歌2 小时前
Redis设计与实现 学习笔记 第二十章 Lua脚本
redis·笔记·学习
2401_858286112 小时前
L13.【LeetCode笔记】合并两个有序数组
c语言·开发语言·数据结构·笔记·算法·leetcode
池佳齐7 小时前
《AI大模型开发笔记》——Prompt提示词最佳实践
人工智能·笔记·prompt
Ice1667 小时前
算法学习笔记(十):位运算、数论等
笔记·学习
尘佑不尘8 小时前
蓝队基础,了解企业安全管理架构
数据库·笔记·安全·web安全·蓝队
特种加菲猫9 小时前
初阶数据结构之队列的实现
开发语言·数据结构·笔记
醉陌离9 小时前
渗透测试学习笔记——shodan(3)
笔记·学习
家有狸花10 小时前
Node.js笔记(四)局域网聊天室2:服务端接受客户端消息
笔记·node.js