200. Number of Islands

Description

Given an m x n 2D binary grid grid which represents a map of '1’s (land) and '0’s (water), return the number of islands.

An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.

Algorithm

This is a classical BFS question. For each position with value “1” in this grid, we use BFS to find all the related "1"s. All the “1” will be recorded in visited and queue until there’s no more “1” connected to this group of positions. Then we move on to the next position which is not in visited and whose value is “1”. We add the 1 to the total number of islands if we find a new “1”. Return the total number of islands after we traverse all the positions in this grid.

Exceptions

if there is not grid, return 0.
In each loop, if the value is “0” or the position has been added to visited before, skip the position. The position has been added to visited before is because this position is “1” and is connected to a previous “1”. So it’s not a new island. It’s in a previous island and has been counted already. So we need to skip it.
Ths same when we find the neighbors. We skip the "0"s because they are not lands and we skip any position that is our of range - beyong the grid. We also need to skip any position that has been added to visited to avoid adding the position into the queue multiple times.


Code

    def numIslands(self, grid: List[List[str]]) -> int:
		'''
		special case
		exception
		'''
        if not grid:
            return 0
        '''
        neighbors can be found in four directions
        keep the position difference in delta
        use this to find neighbors afterwards
        '''
        delta = [(0, 1), (0, -1), (-1, 0), (1, 0)]
        '''
        implement BFS using queue
        we only count the island once
        need to keep a set to store the lands we visited
        '''
        queue = collections.deque()
        visited = set()
        res = 0
        '''
        for each position, we need to check:
        if it's a valid island: not visited and value = "1"
        '''
        for i in range(len(grid)):
            for j in range(len(grid[0])):
                if (i, j) in visited or grid[i][j] == "0":
                    continue
                '''
                if (i, j) is a valid island:
                add (i, j) into queue and visited
                add 1 to the result
                '''
                res += 1
                queue.append((i, j))
                visited.add((i, j))
				'''
				for each valid island
				use bfs to find all the connected "1"s
				until there's no new connected position available
				'''
                while queue:
                    current = queue.popleft()
                    '''
                    find all the valid neighbors:
                    1. neighbor should be in grid
                    2. neighbor should have value "1"
                    3. neighbor not in visited
                    '''
                    for neighbor in self.get_neighbor(current, grid, delta):
                        if neighbor in visited:
                            continue
                        '''
                        add all the valid neighbors into the queue
                        find the neighbor of newly added valid position in next round
                        '''
                        queue.append(neighbor)
                        visited.add(neighbor)
                 '''
                 when queue is empty, end the while loop
                 Now, all the valid neighbors connected to (i, j) have been found
                 move on to next position
                 '''
        '''
        after 2 layers of for loop
        all the position in grid have been checked
        return the result
        '''
        return res
    '''
    define a helper function here to keep main function clear
    find all the "1"s connected to the current position
    current position: the one poped from queue in this round
    need to leverage delta to keep it clean
    '''
    def get_neighbor(self, current, grid, delta):
        neighbors = []
        for dx, dy in delta:
            new_x = current[0] + dx
            new_y = current[1] + dy
            if 0 <= new_x < len(grid) and 0 <= new_y < len(grid[0]) and grid[new_x][new_y] == "1":
                neighbors.append((new_x, new_y))
        return neighbors

Tips

we are using (i, j) as the key of visited set. Python can do this. But we can also convert the position to a number: key = i * num_of_columns + j. This value is unique for all the position in grid. row == i == key // num_of_columns, column == j == key % num_of_columns

Complexity

O(m n) we have to visit all the position in grid and all their neighbors. There are total m x n nodes and each node has 4 neighbors. So it’s 4mn which is O(mn)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值