【问题标题】:Finding areas in 2d array with python使用python查找二维数组中的区域
【发布时间】:2018-07-02 04:57:58
【问题描述】:

假设我有以下二维数组:

[
[1,1,1,2,2],
[1,1,2,3,2],
[2,2,2,3,1],
[2,1,0,3,2],
[2,0,3,3,0]]

可以看出,二维数组中有多个区域具有相同的值,如果一个区域中的单元格数量为5或更高,则值变为0,从而产生以下数组:

[
[0,0,0,2,2],
[0,0,0,0,2],
[0,0,0,0,1],
[0,1,0,0,2],
[0,0,0,0,0]]

我的问题是是否有任何算法可以解决这个问题?我曾尝试在 stackoverflow 或 google 上查找解决方案,但我自己找不到或想出任何解决方案。

【问题讨论】:

  • 为什么右上角“2”的3个单元格不被认为是总和超过5的区域?
  • 对不起,我的意思不是区域中的数字总和,我是指区域中的单元格总数
  • 什么定义了区域?
  • 您想要将哪些元素和所有元素设为 0 ?在您的示例 o/p 中,我没有得到任何逻辑

标签: python arrays algorithm numpy multidimensional-array


【解决方案1】:

您可以使用Flood-Fill algorithm。对于您尚未访问的每个单元格,对所有相邻单元格执行 DFS 或 BFS,除非它们具有不同的值。然后,检查您以这种方式访问​​了多少个单元格,如果至少有 5,则将其设置为 0

seen = set()
for i in range(len(arr)):
    for j in range(len(arr[i])):
        if (i,j) not in seen:
            # start flood-fill from that position
            same = [(i,j)]
            pos = 0
            while pos < len(same):
                x, y = same[pos]
                for x2, y2 in ((x+1,y), (x-1,y), (x,y+1), (x,y-1)):
                    if 0 <= x2 < len(arr) and  0 <= y2 < len(arr[x2]) and \
                            (x2,y2) not in seen and arr[x2][y2] == arr[i][j]:
                        same.append((x2,y2))
                        seen.add((x2,y2))
                pos += 1
            # check size of zone and set to zero
            if len(same) >= 5:
                for i2, j2 in same:
                    arr[i2][j2] = 0

arr 是您的二维数组,结果为

[[0, 0, 0, 2, 2],
 [0, 0, 0, 0, 2],
 [0, 0, 0, 0, 1],
 [0, 1, 0, 0, 2],
 [0, 0, 0, 0, 0]]

【讨论】:

  • 非常感谢,这很有帮助!
【解决方案2】:

这是我解决这个问题的类似 DFS 的方法(复杂度 O(rows * columns)):

# given array
ayyyarray = [
[1,1,1,2,2],
[1,1,2,3,2],
[2,2,2,3,1],
[2,1,0,3,2],
[2,0,3,3,0]]

# function that mark "color" on cell and call take_a_tour for all neighbours with the same number
def take_a_tour(ayyyarray, visited, y, x, act_group_number, group_members_cnt):
    visited[y][x] = act_group_number
    if act_group_number in group_members_cnt:
        group_members_cnt[act_group_number] += 1
    else: 
        group_members_cnt[act_group_number] = 1

    if (x + 1 < len(ayyyarray[y])) and (visited[y][x + 1] == 0) and (ayyyarray[y][x + 1] == ayyyarray[y][x]):
        take_a_tour(ayyyarray, visited, y, x + 1, act_group_number, group_members_cnt)
    if (y + 1 < len(ayyyarray)) and (visited[y + 1][x] == 0) and (ayyyarray[y + 1][x] == ayyyarray[y][x]):
        take_a_tour(ayyyarray, visited, y + 1, x, act_group_number, group_members_cnt)
    if (x - 1 >= 0) and (visited[y][x - 1] == 0) and (ayyyarray[y][x - 1] == ayyyarray[y][x]):
        take_a_tour(ayyyarray, visited, y, x - 1, act_group_number, group_members_cnt)
    if (y - 1 >= 0) and (visited[y - 1][x] == 0 ) and (ayyyarray[y - 1][x] == ayyyarray[y][x]):
        take_a_tour(ayyyarray, visited, y - 1, x, act_group_number, group_members_cnt)

# 0 if not painted, color code(group_number) if already painted
visited = [[0 for _ in range(len(ayyyarray[x]))] for x in range(len(ayyyarray))]
# actual color we are using to paint same cells
act_group_number = 1
# dictionary to store pairs [color : number_of_cells_using_this_color]
group_members_cnt = {}

# for every cell i call take_a_tour.
for y in range(len(ayyyarray)):
    for x in range(len(ayyyarray[y])):
        if not visited[y][x]:
            take_a_tour(ayyyarray, visited, y, x, act_group_number, group_members_cnt)
            act_group_number += 1

# setting 0 for every cell that are painted with color used in >= 5 cells.
for y in range(len(ayyyarray)):
    for x in range(len(ayyyarray[y])):
        if group_members_cnt[visited[y][x]] >= 5:
            ayyyarray[y][x] = 0

# print result
for y in ayyyarray:
    print(y)

【讨论】:

    猜你喜欢
    • 2021-04-20
    • 1970-01-01
    • 2013-03-20
    • 2012-05-29
    • 2021-05-10
    • 1970-01-01
    • 2021-06-09
    • 2017-04-11
    • 1970-01-01
    相关资源
    最近更新 更多