【发布时间】:2023-03-17 17:36:01
【问题描述】:
昨晚我试图解决 leetcode 的 Number of Islands 挑战。我对自己如此迅速地解决它感到非常满意。该解决方案遍历网格的行,直到找到一个有土地的单元格。然后程序进入一个函数,找到所有与陆地(BFS)相邻的单元格,用水替换它们,然后返回。岛屿计数增加,并重复此过程,直到所有细胞都转化为水。
简单吧?但是程序在以下测试用例上停止:
import queue
grid = [
["1","1","1","1","1","0","1","1","1","1","1","1","1","1","1","0","1","0","1","1"],
["0","1","1","1","1","1","1","1","1","1","1","1","1","0","1","1","1","1","1","0"],
["1","0","1","1","1","0","0","1","1","0","1","1","1","1","1","1","1","1","1","1"],
["1","1","1","1","0","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1"],
["1","0","0","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1"],
["1","0","1","1","1","1","1","1","0","1","1","1","0","1","1","1","0","1","1","1"],
["0","1","1","1","1","1","1","1","1","1","1","1","0","1","1","0","1","1","1","1"],
["1","1","1","1","1","1","1","1","1","1","1","1","0","1","1","1","1","0","1","1"],
["1","1","1","1","1","1","1","1","1","1","0","1","1","1","1","1","1","1","1","1"],
["1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1"],
["0","1","1","1","1","1","1","1","0","1","1","1","1","1","1","1","1","1","1","1"],
["1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1"],
["1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1"],
["1","1","1","1","1","0","1","1","1","1","1","1","1","0","1","1","1","1","1","1"],
["1","0","1","1","1","1","1","0","1","1","1","0","1","1","1","1","0","1","1","1"],
["1","1","1","1","1","1","1","1","1","1","1","1","0","1","1","1","1","1","1","0"],
["1","1","1","1","1","1","1","1","1","1","1","1","1","0","1","1","1","1","0","0"],
["1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1"],
["1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1"],
["1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1"]
]
def print_grid(grid):
for idxr, row in enumerate(grid):
for idxc, cell in enumerate(row):
print(f"[{grid[idxr][idxc]}]", end="")
print("")
print("\n----\n")
def nuke_island(grid, idxr, idxc):
"""Traverses and destroys an island."""
# Create a queue of our first cell
island_cells = queue.Queue()
island_cells.put((idxr, idxc))
# Process our queue
while not island_cells.empty():
# Retrieve a new cell from queue
idxr, idxc = island_cells.get()
# Replace new cell with water
grid[idxr][idxc] = "0"
#Try to add all valid connecting cells to the queue
for row, col in [(idxr-1, idxc), (idxr+1, idxc), (idxr, idxc-1), (idxr, idxc+1)]:
# Don't allow python to backwards-index
if row < 0 or col < 0:
continue
try:
# Retieve the connecting cell
cell = grid[row][col]
# If the cell is land, add it to the queue
if cell == "1":
island_cells.put((row, col))
except IndexError:
# We went off the map, continue
continue
# We've processed all connecting cells and nuked the whole island, return updated grid
return grid
# Set number of islands to zero
islands = 0
# Iterate through the grid
for idxr, row in enumerate(grid):
for idxc, cell in enumerate(row):
# If our cell is land, enter nuke_island
if cell == '1':
grid = nuke_island(grid, idxr, idxc)
islands += 1
# Return the number of total islands
print(f"Islands: {islands}")
如果您查看上面的示例,您可以看到网格只有一个岛。 程序从单元格 [0][0] 开始,进入 nuke_island() 子程序,然后卡在那里。 如果您使用 print_grid() 调试功能,您可以看到程序将陆地单元格删除为预计到某一点,然后停止。问题是队列“island_cells”。
由于某种原因,队列的增长速度比删除项目的速度还要快,并且会永远增长。我不知道为什么,因为以前的测试用例不会发生这种情况,甚至以前的测试用例只有一个岛。 如果我用代码中的列表替换队列:
grid = [
["1","1","1","1","1","0","1","1","1","1","1","1","1","1","1","0","1","0","1","1"],
["0","1","1","1","1","1","1","1","1","1","1","1","1","0","1","1","1","1","1","0"],
["1","0","1","1","1","0","0","1","1","0","1","1","1","1","1","1","1","1","1","1"],
["1","1","1","1","0","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1"],
["1","0","0","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1"],
["1","0","1","1","1","1","1","1","0","1","1","1","0","1","1","1","0","1","1","1"],
["0","1","1","1","1","1","1","1","1","1","1","1","0","1","1","0","1","1","1","1"],
["1","1","1","1","1","1","1","1","1","1","1","1","0","1","1","1","1","0","1","1"],
["1","1","1","1","1","1","1","1","1","1","0","1","1","1","1","1","1","1","1","1"],
["1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1"],
["0","1","1","1","1","1","1","1","0","1","1","1","1","1","1","1","1","1","1","1"],
["1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1"],
["1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1"],
["1","1","1","1","1","0","1","1","1","1","1","1","1","0","1","1","1","1","1","1"],
["1","0","1","1","1","1","1","0","1","1","1","0","1","1","1","1","0","1","1","1"],
["1","1","1","1","1","1","1","1","1","1","1","1","0","1","1","1","1","1","1","0"],
["1","1","1","1","1","1","1","1","1","1","1","1","1","0","1","1","1","1","0","0"],
["1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1"],
["1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1"],
["1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1"]
]
def print_grid(grid):
for idxr, row in enumerate(grid):
for idxc, cell in enumerate(row):
print(f"[{grid[idxr][idxc]}]", end="")
print("")
print("\n----\n")
def nuke_island(grid, idxr, idxc):
"""Traverses and destroys an island."""
# Create a list of our first cell
island_cells = [(idxr, idxc)]
# Process our list
while len(island_cells) > 0:
# Retrieve a new cell from queue
(idxr, idxc) = island_cells.pop()
# Replace new cell with water
grid[idxr][idxc] = "0"
# Try to add all valid connecting cells to the queue
for (row, col) in [(idxr-1, idxc), (idxr+1, idxc), (idxr, idxc-1), (idxr, idxc+1)]:
# Don't allow python to backwards-index
if row < 0 or col < 0:
continue
try:
# Retieve the connecting cell
cell = grid[row][col]
# If the cell is land, add it to the queue
if cell == "1":
island_cells.append((row, col))
except IndexError:
# We went off the map, continue
continue
# We've processed all connecting cells and nuked the whole island, return updated grid
return grid
# Set number of islands to zero
islands = 0
# Iterate through the grid
for idxr, row in enumerate(grid):
for idxc, cell in enumerate(row):
# If our cell is land, enter nuke_island
if cell == '1':
grid = nuke_island(grid, idxr, idxc)
islands += 1
# Return the number of total islands
print(f"Islands: {islands}")
程序现在按预期运行。 即使我将列表与 FIFO 队列互换使用。那么发生了什么?为什么队列无限增长?我错过了什么明显的东西吗?
【问题讨论】:
-
append(...) / pop() 实际上是 LIFO 而不是 FIFO 所以你已经切换到 DFS
-
是的,我刚刚注意到了!我来这里是为了更新问题。尽管如此,为什么使用 BFS 会永远挂起并且似乎不断地将项目添加到队列中?只有 400 个单元格。
-
可能你从来没有重复数据删除——你需要调试它(这与 stackoverflow 无关)
标签: python python-3.x list queue breadth-first-search