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
变量的值不会被意外修改,从而确保代码能够正确地遍历和处理网格中的每个位置。