python - 递归查找二维列表中相同元素的最长路径

我需要在 2d 矩阵中递归地找到 0 的最长路径,但不知道该怎么做。(从给定的 (i , j) 它只能向上、向下、向右或向左移动)

例如这个矩阵:

mat = [[1, 0, 0, 3, 0],
       [0, 0, 2, 3, 0],
       [2, 0, 0, 2, 0],
       [0, 1, 2, 3, 3]]
    print(question3_b(mat))

这应该返回 6,因为有大小为 1、3、6 的社区。我的尝试:我创建了一些包装函数来查找列表中的最大值,并创建了一个函数来查找给定 (i,j) 元素的路线并将其添加到列表中,并在每个点上执行此操作 (i,j ) 在矩阵中。

def question3_b(mat) -> int:
    rows: int = len(mat)
    cols: int = len(mat[0])
    community_lengths = list()
    for i in range(rows):
        for j in range(cols):
            visited = zeros(rows, cols)  # create a 2d list of 0's with size rows,cols
            a = findcommunity(mat, (i, j), visited)
            print("a=", a)
            community_lengths.append(a)
    print(community_lengths)
    return findmax(community_lengths)


def findcommunity(mat: list, indices: tuple, visited: list):  # find length of community
    #global rec_counter
    #rec_counter += 1
    i, j = indices
    rows = len(mat)
    cols = len(mat[0])
    if mat[i][j] == 0:
        visited[i][j] = 1
        if i < rows - 1:
            if visited[i + 1][j] == 0:
                return 1 + findcommunity(mat, (i + 1, j), visited)
        if j < cols - 1:
            if visited[i][j + 1] == 0:
                return 1 + findcommunity(mat, (i, j + 1), visited)
        if i > 0:
            if visited[i - 1][j] == 0:
                return 1 + findcommunity(mat, (i - 1, j), visited)
        if j > 0:
            if visited[i][j - 1] == 0:
                return 1 + findcommunity(mat, (i, j - 1), visited)
    else:  # mat[i][j]!=0

        return 0

def zeros(rows:int,cols:int)->list: #create a 2d matrix of zeros with size (rows,cols)
    if rows==1 and cols==1:return [[0]]
    if rows==1 and cols>1:return [[0]*cols]
    if rows>1 and cols>1:return zeros(rows-1,cols)+zeros(1,cols)
def findmax(arr:list)->int: # find max in an array using recursion
    if len(arr)==2:
        if arr[0]>arr[1]:return arr[0]
        else:return arr[1]
    else:
        if arr[0]>arr[1]:
            arr[1]=arr[0]
            return findmax(arr[1:])
        else:
            return findmax(arr[1:])

我哪里做错了?对于 4X4 零矩阵,我希望它运行 16*16 次[每个 i,j 16 次,矩阵中有 16 个元素]。但它只运行一次。 zeros 是我制作的递归函数,其功能类似于 np.zeros,它创建一个 2d 矩阵,其中包含指定大小的 0。

回答1

它变得非常混乱,但我试图只更改您的代码而不是编写新的解决方案。你应该看看 collections deque。多次看到这一点,人们更容易跟踪 visited

我将访问更改为循环外部并用 np.zeros 定义它(没有你的功能;))。我不确定您在返回时的递归函数调用是否错误,但您的 if 语句是错误的,或者至少是它背后的逻辑(或者我不明白,也可能:))我完全改变了那个块。当您第一次在 mat 中遇到 0 时,递归部分将深入到 mat,只要它找到另一个 0 左、右、下或上(这就是 dc 背后的功能)和 dr)。这就是 community_counter 增加的地方。如果函数最后一次返回并且您跳到 question_3b 中的外循环,则计数器将重置并搜索下一个 0(另一个社区的下一个开始)。

import numpy as np

def question3_b(mat) -> int:
    rows: int = len(mat)
    cols: int = len(mat[0])
    community_lengths = list()
    visited = np.zeros((rows, cols))  # create a 2d list of 0's with size rows,cols
    community_count = 0
    for row in range(rows):
        for col in range(cols):
            if visited[row][col]==0:
                community_count,visited = findcommunity(mat, (row, col), visited, community_count)
                if community_count!=0:
                    community_lengths.append(community_count)
                community_count=0
    return community_lengths


def findcommunity(mat: list, indices: tuple, visited: list,community_count: int):  # find length of community
    i, j = indices
    rows = len(mat)
    cols = len(mat[0])
    visited[i][j] = 1
    if mat[i][j] == 0:
        community_count += 1
        dr = [-1, 0, 1, 0]
        dc = [0,-1, 0, 1]
        for k in range(4):
            rr = i + dr[k]
            cc = j + dc[k]
            if 0<=rr<rows and 0<=cc<cols:
                if visited[rr][cc]==0 and mat[rr][cc]==0:
                    community_count, visited = findcommunity(mat, (rr,cc), visited, community_count)
        return community_count,visited
    else:
        return community_count,visited

mat = [[1, 0, 0, 3, 0],
       [0, 0, 2, 3, 0],
       [2, 0, 0, 2, 0],
       [0, 1, 2, 3, 3]]

all_communities = question3_b(mat)
print(all_communities)
# [6, 3, 1]
print(max(all_communities))
# 6

编辑

这是您使用的 findcommunity 函数。对其进行了测试,它也可以正常工作。

def findcommunity(mat: list, indices: tuple, visited: list,community_count: int):  # find length of community
    i, j = indices
    rows = len(mat)
    cols = len(mat[0])
    visited[i][j] = 1
    if mat[i][j] == 0:
        community_count += 1
        if i < rows - 1:
            if visited[i + 1][j] == 0:
                community_count, visited = findcommunity(mat, (i + 1, j), visited, community_count)
        if j < cols - 1:
            if visited[i][j + 1] == 0:
                community_count, visited = findcommunity(mat, (i, j + 1), visited, community_count)
        if i > 0:
            if visited[i - 1][j] == 0:
                community_count, visited = findcommunity(mat, (i - 1, j), visited, community_count)
        if j > 0:
            if visited[i][j - 1] == 0:
                community_count, visited = findcommunity(mat, (i, j - 1), visited, community_count)
        return community_count,visited
    else:
        return community_count,visited

回答2

这是一种完全不同的方法,以防有人感兴趣。

import numpy as np

mat = [[1, 0, 0, 3, 0],
         [0, 0, 2, 3, 0],
         [2, 0, 0, 2, 0],
         [0, 1, 2, 3, 3]]
mat = np.array(mat)

# some padding of -1 to prevent index error
mask = np.full(np.array(mat.shape) + 2,  -1)
mask[1:-1, 1:-1 ] = mat

# visiteds are set to -2
def trace(f, pt):
    mask[tuple(pt)], pts = -2, [pt - 1]
    pts += [trace(f, pt + d) for d in 
([0, 1], [1, 0], [0, -1], [-1, 0]) if 
mask[tuple(pt + d)] == f]
    return pts

clusters = lambda f: {tuple(pt-1): trace(f, pt) for pt in np.argwhere(mask==f) if mask[tuple(pt)]==f}

# now call with value your looking for
print(clusters(0))

相似文章

scala - 多个列表的组合 (Scala)

我正在尝试编写一个函数,该函数将多个列表作为输入并返回这些列表之间每个组合的字符串表示形式。样本输入:valintegers=List(1,2,3,4)valcharacters=List('a','...

随机推荐

最新文章