使用python查找2d数组中的区域

时间:2018-01-23 11:27:26

标签: python arrays algorithm numpy multidimensional-array

假设我有以下2d数组:

[
[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]]

可以看出,2d数组中的区域具有相同的值,如果区域中的单元格数量为5或更高,则值变为零,从而产生以下数组:

[
[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 个答案:

答案 0 :(得分:0)

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

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作为您的2D数组,将结果显示为

[[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]]

答案 1 :(得分:0)

这是我解决此问题的DFS方法(复杂性O(行*列)):

# 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)