【问题标题】:counter in recursiv function递归函数中的计数器
【发布时间】:2022-01-14 13:22:32
【问题描述】:

我在python中有以下递归函数:

def _floodfill(matrix, x, y, counter):
    if matrix[x][y] != 9:
        matrix[x][y] = 9
        counter += 1
        # recursively invoke flood fill on all surrounding cells:
        if x > 0:
            counter += int(_floodfill(matrix, x - 1, y, counter) or 0)
        if x < len(matrix) - 1:
            counter += int(_floodfill(matrix, x + 1, y, counter) or 0)
        if y > 0:
            counter += int(_floodfill(matrix, x, y - 1, counter) or 0)
        if y < len(matrix[0]) - 1:
            counter += int(_floodfill(matrix, x, y + 1, counter) or 0)
        return counter

我想计算这个函数被调用的频率,分别计算该区域中有多少个数字!= 9。 使用下面的矩阵并调用函数,如:_floodfill(matrix,1,1,0) 该函数应返回 2:

[[9,9,9],
 [9,2,9],
 [9,3,9],
 [9,9,9]]

我的代码有什么问题?

编辑 我认为这个函数更具可读性:

def _floodfill(matrix, x, y, counter):
    if matrix[x][y] != 9:
        matrix[x][y] = 9
        counter += 1
        # recursively invoke flood fill on all surrounding cells:
        if x > 0:
            counter += _floodfill(matrix, x - 1, y, counter)
        if x < len(matrix) - 1:
            counter += _floodfill(matrix, x + 1, y, counter)
        if y > 0:
            counter += _floodfill(matrix, x, y - 1, counter)
        if y < len(matrix[0]) - 1:
            counter += _floodfill(matrix, x, y + 1, counter)
        return counter
    else:
        return 0

【问题讨论】:

  • 你测试了吗?我怀疑你能得到这样的正确计数。大多数情况下,你return counter;然后你在counter += _floodfill(...) 中使用这个返回值。所以,counter 每次递归调用至少翻倍。

标签: python recursion


【解决方案1】:

使用列表保存计数器,因为int是按值传递的:

def _floodfill(matrix, x, y, counter):
    if matrix[x][y] != 9:
        matrix[x][y] = 9
        counter[0] += 1
        # recursively invoke flood fill on all surrounding cells:
        if x > 0:
            _floodfill(matrix, x - 1, y, counter)
        if x < len(matrix) - 1:
            _floodfill(matrix, x + 1, y, counter)
        if y > 0:
            _floodfill(matrix, x, y - 1, counter)
        if y < len(matrix[0]) - 1:
            _floodfill(matrix, x, y + 1, counter)
        return counter
    else:
        return 0
_floodfill([[9,9,9],
            [9,2,9],
            [9,3,9],
            [9,9,9]], 1, 1, [0])

【讨论】:

  • 使用具有单个元素的列表来模拟“可变 int”有点笨拙,并且使代码非常难以理解。
【解决方案2】:

三个备注:

  1. 您无需将counter 传递给您的递归调用。他们需要它做什么? counter 持有人数 以前访问过的单元格。您的递归调用不需要知道您已经访问了多少个单元格。该信息反过来:您想要的是递归调用告诉您他们访问了多少个单元格。

  2. 如果if/else 中的所有分支都具有一致的return 值,则编写函数和使用函数会容易得多。如果函数有时返回访问过的单元格数,有时返回None,使用起来超级不方便;请注意您必须在每次递归调用后添加 int(...) or 0 以解决该问题。

  3. 您的矩阵存储为列表列表的方式,对我来说,用y 索引行和用x 索引列比其他方式更有意义。

def _floodfill(matrix, y, x):
    if matrix[y][x] == 9:
        return 0
    else:
        matrix[y][x] = 9
        counter = 1
        if x > 0:
            counter += _floodfill(matrix, y, x - 1)
        if x < len(matrix) - 1:
            counter += _floodfill(matrix, y, x + 1)
        if y > 0:
            counter += _floodfill(matrix, y - 1, x)
        if y < len(matrix[0]) - 1:
            counter += _floodfill(matrix, y + 1, x)
        return counter

mat = [
 [9,9,9],
 [9,2,9],
 [9,3,9],
 [9,9,9]
]

c = _floodfill(mat, 1, 1)
print(c)
print(mat)

# 2
# [[9, 9, 9], [9, 9, 9], [9, 9, 9], [9, 9, 9]]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-04
    • 1970-01-01
    • 1970-01-01
    • 2022-11-25
    • 1970-01-01
    相关资源
    最近更新 更多