Вопрос гласит следующее: Учитывая непустую сетку двумерного массива из 0 и 1, остров - это группа из 1 (представляющая землю), соединенная 4-мя направлениями (горизонтальная или вертикальная). Вы можете предположить, что все четыре ребра сетки являются в окружении воды.

Найти максимальную площадь острова в данном двумерном массиве. (Если острова нет, максимальная площадь равна 0.)

class Solution:

    def maxAreaOfIsland( self, grid: List[List[int]]) -> int:
        a = len(grid)


        for x in range(0, a):
            b = len(grid[x])
            for y in range(0 , b):
                if grid[x][y] == "1":
                    self.dfs(grid , x , y)

        return count

    def dfs(self,grid, i, j):
        count = 0

        if i < 0 or i >= len(grid) or j < 0 or j >= len(grid[0]) or grid[i][j] == "0" or grid[i][j] == "2":
            return 

        grid[i][j] = "2"
        count += 1

        self.dfs(grid , i-1 , j)
        self.dfs(grid , i+1, j)
        self.dfs(grid, i , j-1)
        self.dfs(grid , i , j+1)

Я пытаюсь использовать метод поиска в глубину, чтобы найти соседей. Тем не менее, я понятия не имею, как правильно увеличить счетчик при поиске «1», а также при выводе общего количества. Может кто-нибудь поможет мне, пожалуйста?

3
user12852585 20 Апр 2020 в 13:06

2 ответа

Вы можете сделать это без рекурсивности, создав словарь координат (наборов) для позиций, которые находятся на суше. Затем объедините эти наборы для каждой позиции земли, которая соединяется справа или ниже других позиций земли. Результатом будет общий набор позиций на всех связанных позициях. Длина самого большого из этих наборов составит площадь самого большого острова:

def maxIsland(grid):
    rows,cols = len(grid),len(grid[0])
    land      = { (r,c):{(r,c)} for r in range(rows) for c in range(cols) if grid[r][c] }
    for (r,c) in list(land):
        for nr,nc in [(r+1,c),(r,c+1)]:            # Positions below/right 
            if (nr,nc) not in land:  continue      # connecting land 
            if land[r,c] is land[nr,nc]: continue  # skip already merged
            land[r,c].update(land[nr,nc])          # Merge set of positions 
            for (lr,lc) in land[nr,nc]: 
                land[lr,lc] = land[r,c]            # Propagate merged set to all
    return max(map(len,land.values()))             # return size of largest set

Выход:

world = [ "0000000000000",
          "0111000000111",
          "0101110000111",
          "0100111100111",
          "0100000100000",
          "0101001110000",
          "0111001110000" ]
world = [ list(map(int,row)) for row in world ]

print( maxIsland(world) ) # 25

Для еще более базового подхода вы можете работать с набором наземных координат и постепенно извлекать координаты, которые связаны с островами, при измерении размеров островов. Острова могут быть сформированы путем расширения одной наземной координаты, добавления неизведанных соседей и расширения новых добавленных позиций острова:

def maxIsland(grid):
    rows,cols = len(grid),len(grid[0])
    land      = { (r,c) for r in range(rows) for c in range(cols) if grid[r][c] }
    result    = 0
    while land:                    # find new islands in uncharted land
        island    = [land.pop()]           # pick a coordinate to expand into an island
        expanding = 0                      # will expand coordinates added by expansion
        while expanding<len(island):
            r,c = island[expanding]                         # expand added coordinate 
            neighbours = {(r+1,c),(r-1,c),(r,c+1),(r,c-1)}  # candidate coordinates
            island    += list(land & neighbours)            # add uncharted land to island
            land      -= neighbours                         # remove from uncharted land
            expanding += 1                                  
        result = max(result,len(island))   # track largest island
    return result

Примечание: это будет работать намного быстрее, чем первый в больших сетках

0
Alain T. 26 Апр 2020 в 22:34

Чтобы иметь возможность увеличить счет в рекурсивной функции, это должна быть переменная класса или глобальная переменная. Вы также пытаетесь сбросить его на 0 каждый раз, когда входите в dfs, что не очень хорошо, потому что ваша функция dfs будет вызывать себя и сбрасывать это число до 0. Ваша основная идея в порядке, вы помечаете уже посещенные части как " 2 " . Единственное, что также может быть изменено, - это проверка, которую вы делаете по краям. Проблема состоит в том, что вы можете предположить, что все ребра равны 0, поэтому вы можете просто начать итерацию с позиции 1,1 вместо 0,0, потому что вы никогда не выйдете за пределы карты, выполнив команду dfs.

Место, где вы должны сбросить счетчик, находится в функции maxAreaOfIsland всякий раз, когда вы найдете плитку «1». Также вы можете проверить после dfs, больше ли он, чем максимум, который вы нашли.

class Solution:
    def __init__(self):
        self._count = 0   # You need the count to be visible for both functions, so you can declare it here
        self._maxCount = 0 # Max count doesn't have to be declared here, you can also declare it inside maxAreaOfIsland   

    def maxAreaOfIsland(self, grid):
        a = len(grid)


        for x in range(0, a):
            b = len(grid[x])
            for y in range(0 , b):
                if grid[x][y] == "1":
                    self._count = 0   # Here you reset the count
                    self.dfs(grid , x , y)
                    if self._count > self._maxCount:  # Here you check if it's greater than the max
                        self._maxCount = self._count

        return self._maxCount

    def dfs(self,grid, i, j):

        if i < 0 or i >= len(grid) or j < 0 or j >= len(grid[0]) or grid[i][j] == "0" or grid[i][j] == "2":
            return 

        grid[i][j] = "2"
        self._count += 1 # Here you increment the count

        self.dfs(grid , i-1 , j)
        self.dfs(grid , i+1, j)
        self.dfs(grid, i , j-1)
        self.dfs(grid , i , j+1)
0
Ghosty Frosty 23 Апр 2020 в 16:09