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

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而已!!!我完全不懂为什么这样啊啊啊啊!

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

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

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

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)

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

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)

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

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

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

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

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

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

相关推荐
优选资源分享6 小时前
PicGo v3.0.3 新版 | 开源免费图床工具
javascript·笔记·electron
星恒随风7 小时前
Linux线程概念详解:从分页存储、页表、MMU与TLB,深入理解线程和进程的区别与联系
linux·运维·笔记·学习·状态模式
qq_284274057 小时前
数控机床编程基础与坐标系:编程六步流程、程序号/程序段/程序字格式,与右手定则下车床铣床XYZ轴判定(含考点)
笔记·学习·自动化·制造
问心无愧05138 小时前
[SUCTF 2019]EasySQL
笔记
ss2738 小时前
PG实战笔记 | 09 PostgreSQL psql客户端基本操作
数据库·笔记·postgresql
xxwl5858 小时前
区域赛分类题解
c++·笔记·学习·算法
成都蜀味缘餐饮技术培训学校11 小时前
油炸串串技术培训实战指南,核心食材选购与预处理标准
数据仓库·经验分享·笔记·课程设计·微信公众平台
摇滚侠11 小时前
《大模型应用开发实践:基于 Spring AI+DeepSeek 实现》第 11 章 大模型技术概览 阅读笔记 1
人工智能·笔记·spring
xxwl58512 小时前
区域赛算法模版第八章---贪心(Greedy)
c++·笔记·学习·算法
知产xiao_xin13 小时前
专利立法及修改
经验分享·笔记·知识产权