需要帮助来了解此python深度优先搜索代码

时间:2019-04-02 06:33:13

标签: python graph dfs

我是Python编码的新手,很难理解下面的代码。在图论上,使用DFS在所有岛屿区域中找到最大的区域。 1代表岛屿,0代表网格中的水。

def maxAreaOfIsland(grid):
    row, col = len(grid), len(grid[0])
    def dfs(i, j):
        if 0 <= i <= row - 1 and 0 <= j <= col - 1 and grid[i][j]:
            grid[i][j] = 0

#scans through all rows & cols and 
#turns number in the grid into 0 if all conditions are true?

            return  1 + dfs(i - 1, j) + dfs(i + 1, j) + dfs(i, j - 1) + dfs(i, j + 1)
        return 0  

# recursive function that checks up, down, left, right in the grid. 
# when does it return 1?

    return max(dfs(i, j) for i in range(row) for j in range(col))

maxAreaOfIsland([[1,0,1,1,1],
                 [0,0,0,1,1],
                 [1,1,1,0,1]]) 
Out: 6

我添加了一些评论,这些评论反映了我到目前为止的理解,但不确定是否正确。从第4行开始,我很困惑,尤其是递归部分。 有人可以详细解释吗?通常,这类代码倾向于排队/出队,以记录是否已探访过该岛,但我认为该代码不具备该功能?

1 个答案:

答案 0 :(得分:1)

我想这个问题实际上是关于理解算法而不是Python。提供的Python代码非常简单。

该代码包含函数maxAreaOfIsland,该函数又包含递归函数dfs。这两个函数构成2个计算层。让我们分别查看这些层。

# outer layer
def maxAreaOfIsland(grid):
    row, col = len(grid), len(grid[0])
    # function dfs() definition
    return max(dfs(i, j) for i in range(row) for j in range(col))

因此,外层非常简单-为所有可能的dfs(i, j)i计算j,然后选择最大计算值。

# inner layer - slightly modified
def dfs(i, j):
    # recursive case
    if (0 <= i <= row - 1 and 0 <= j <= col - 1) and grid[i][j] == 1:
        grid[i][j] = 0  # this is how we remember visited cells since we don't count zeros
        # optional prints to look at the grid during computation
        # print(i, j)
        # print(*grid, sep='\n', end='\n\n')
        count_current = 1
        count_neighbors = dfs(i - 1, j) + dfs(i + 1, j) + dfs(i, j - 1) + dfs(i, j + 1)
        return  count_current + count_neighbors
    # trivial case and out-of-borders case
    else:
        return 0

内层稍微复杂一点。它能做什么? (1)它得到ij。 (2)如果单元格包含0,则说明情况很简单(水),或者我们不在网格中-只需返回0。 (3)如果单元格包含1,则它是递归的情况(land)-函数开始计算与给定单元格相邻的所有1的数量,每个1都变成{{ 1}},以避免重复计算。

您的示例网格具有3行(0、1、2)和5列(0、1、2、3、4)。假设我们在0。是i = 0, j = 2。我们将其计数(当前结果为1),将其变成1并逐一查看其邻居-上一个邻居不在网格中,下一个邻居为0,左邻居为{{1 }},右邻居是0。我们不返回当前结果,而是继续进行右边的neigbor 0。我们计算它(当前结果为2),将其变成1并查看邻居。上一个邻居不在网格内,下一个邻居为i = 0, j = 3。我们在这里停止,我们不返回当前结果,我们记得还有2个邻居,我们进入了底部的邻居0。我们计算它(当前结果是3),将其变成1并查看邻居。上一个邻居是i = 1, j = 3。我们在这里停止,我们不返回当前结果,我们还记得大约3个邻居,我们进入了上一个邻居0。依此类推。

我的建议是绘制一个简单的示例网格(用笔在一张纸上),并对其手动应用dfs算法。