433. 岛屿的个数
433. 岛屿的个数
中文English
给一个 01 矩阵,求不同的岛屿的个数。
0 代表海,1 代表岛,如果两个 1 相邻,那么这两个 1 属于同一个岛。我们只考虑上下左右为相邻。
样例
样例 1:
输入:
[
[1,1,0,0,0],
[0,1,0,0,1],
[0,0,0,1,1],
[0,0,0,0,0],
[0,0,0,0,1]
]
输出:
3
样例 2:
输入:
[
[1,1]
]
输出:
1
输入测试数据 (每行一个参数)如何理解测试数据?
DFS写法(递归找寻当前岛屿所有关联的岛屿,赋值False)
class Solution: """ 大致思路: 1.主函数,循环grid,只要是True,就说明是新的岛屿,然后写一个dfs方法找寻该岛屿关联的所有岛屿 """ def numIslands(self, grid): # write your code here #dfs写法,递归找寻,一直关联查找 if not grid: return 0 len_x, len_y = len(grid), len(grid[0]) count = 0 direction = [[0,1],[0,-1],[1,0],[-1,0]] #当前岛屿所关联的都会被找到,赋值False def dfs(x, y): #递归找寻,注意,当grid[x][y]是非岛屿的时候,也是不符合递归条件的 if (x < 0 or y < 0 or x > len_x - 1 or y > len_y - 1 or not grid[x][y]): return #当前岛屿递归找寻 grid[x][y] = False dfs(x + 1, y) dfs(x - 1, y) dfs(x, y + 1) dfs(x, y - 1) #主函数 for i in range(len_x): for j in range(len_y): if (grid[i][j]): count += 1 #找寻该岛屿所关联的所有岛屿,都当做一个岛屿来看 dfs(i, j) return count
BFS写法(当前岛屿四周找寻符合条件的岛屿,一直不停的四周循环)
class Solution: """ @param grid: a boolean 2D matrix @return: an integer """ def numIslands(self, grid): # write your code here #bfs写法,四周的找寻,放进队列里面,一直不停的找寻队列为岛屿的四周 if not grid: return 0 len_x, len_y = len(grid), len(grid[0]) count = 0 queue = [] directon = [[1,0],[-1,0],[0,1],[0,-1]] def bfs(x, y): queue.append([x, y]) while queue: pop_num = queue.pop(0) pop_x = pop_num[0] pop_y = pop_num[1] #四周的找寻 for d in directon: new_x = d[0] + pop_x new_y = d[1] + pop_y #如果是这种情况,跳出处理 if (new_x < 0 or new_y < 0 or new_x > len_x - 1 or new_y > len_y - 1): continue #否则判断是否是 if (grid[new_x][new_y]): queue.append([new_x,new_y]) grid[new_x][new_y] = False #主函数 for i in range(len_x): for j in range(len_y): if (grid[i][j]): count += 1 #当前岛屿四周不停的找寻符合条件的,赋值False bfs(i, j) return count
dfs会一直不停的找到当前该岛屿所关联的全部岛屿。而bfs只会找到当前岛屿的四周(上下左右),判断是否符合条件,不停的pop,append进行关联过去
并查集(UnionFind)
大致思路:当前节点判断是否和左上两个节点根节点相同,如果不同(一定不同,每个节点最开始指向自己),且相邻,说明是同一个岛屿 count -= 1
如果左上没有True,则当前是新的岛屿,count不变。(判断,右下效果一样)
class Solution: """ @param grid: a boolean 2D matrix @return: an integer """ def __init__(self): self.count = 0 def numIslands(self, grid): # write your code here #并查集写法,每次需要考察右下两个方向的点,如果是相邻的点,则岛屿个数不加1 #如果是相邻的两个点,则指向同一个根节点,相连 if not grid: return 0 #初始化 len_x, len_y = len(grid), len(grid[0]) father = {} for i in range(len_x): for j in range(len_y): if grid[i][j]: self.count += 1 cur = str(i) + 'and' + str(j) father[cur] = cur # def connect(num1, num2): root_num1 = unionfind(num1) root_num2 = unionfind(num2) if (root_num1 != root_num2): father[root_num2] = root_num1 self.count -= 1 def unionfind(num): orign_num = num if num == father[num]: return num while num != father[num]: num = father[num] #压缩路径 while father[orign_num] != num: temp = father[orign_num] father[orign_num] = num orign_num = temp return num for i in range(len_x): for j in range(len_y): if (grid[i][j]): cur = str(i) + 'and' + str(j) if (i - 1 >= 0 and grid[i - 1][j]): cur_new = str(i - 1) + 'and' + str(j) connect(cur, cur_new) if (j - 1 >= 0 and grid[i][j - 1]): cur_new = str(i) + 'and' + str(j - 1) connect(cur, cur_new) return self.count