题目是这样的:
其实看到这个题目就想到在图像分割中用到的一些算法,有点区域生长的意思,所以初步的思路就是像图像分割那样把每个独立块的1用不同的label贴上,最后label有几个,岛屿就有几个。
然后仔细深入这个想法,首先从图像上一个没有label的点出发贴上label,搜索其四领域,是1则贴上相同label,再对这些贴上label的点搜索四领域,直到一片搜索完成。
这里有两点。
1.怎样完成迭代搜索这个动作?-- 用队列。
2.标记一块搜索完成? – 队列空。
到这里其实就能发现,这里的搜索对应的是一个深度优先搜索,而且并不需要不同的label来标记,只需要记录需要几次能够将所有的1遍历到。
所以进一步的想法是:用一个同大小的矩阵,记作label矩阵,其中为0表示没有遍历到,为1则为遍历到。
那整个算法的流程就是:
1.先把label矩阵中对应原矩阵中的0处标记为1,因为0不需要遍历。
2.一个while循环,当label矩阵中还存在0时,重复动作:找一个岛+计数器++。
3.找一个岛具体为:从label矩阵中一个为0的点出发,标记它为1,在原矩阵中搜索四领域,将为1的点入队,然后它本身出队,重复直到队空。(深度优先搜索)
具体代码如下:
def numIslands(grid):
h = len(grid[0]) # 列
w = len(grid) # 行
'''
这里w和h的定义有些混淆,按英文意应该互换
'''
#print("**",w,"**",h)
island_num = 0
# get the label list to mark the already get one
label = []
for i in range(w*h):
label.append(0)
# firstly we set the 0s marked coz they don't need to find
for i in range(w):
for j in range(h):
if grid[i][j] == 0:
label[i*h+j] = 1
# print(label)
while(label.count(0)!=0):
# find an island and mark it in label
FindAnIsland(grid,label,w,h)
island_num+=1
return island_num
def FindAnIsland(islandmap,label,w,h):
stack = []
start = label.index(0)
label[start] = 1
i = int(start/h)
j = start%h
stack.append(i)
stack.append(j)
# 深度优先搜索
while(stack != []):
#up
if stack[0] == 0:
pass
else:
if islandmap[stack[0]-1][stack[1]] == 1 and label[(stack[0]-1)*h+stack[1]] == 0:
label[(stack[0]-1)*h+stack[1]] = 1
stack.append(stack[0]-1)
stack.append(stack[1])
#down
if stack[0]+1 == w:
pass
else:
if islandmap[stack[0]+1][stack[1]] == 1 and label[(stack[0]+1)*h+stack[1]] == 0:
label[(stack[0]+1)*h+stack[1]] = 1
stack.append(stack[0]+1)
stack.append(stack[1])
#right
if stack[1]+1 == h:
pass
else:
if islandmap[stack[0]][stack[1]+1] == 1 and label[(stack[0])*h+stack[1]+1] == 0:
label[(stack[0])*h+stack[1]+1] = 1
stack.append(stack[0])
stack.append(stack[1]+1)
#left
if stack[1] == 0:
pass
else:
if islandmap[stack[0]][stack[1]-1] == 1 and label[(stack[0])*h+stack[1]-1] == 0:
label[(stack[0])*h+stack[1]-1] = 1
stack.append(stack[0])
stack.append(stack[1]-1)
# print(stack)
# print('-----')
stack.pop(0)
stack.pop(0)
if __name__ == "__main__":
a = []
for i in range(3):
a.append([])
for j in range(3):
a[i].append(eval(input("0 or 1: ")))
#print(a)
island = numIslands(a)
print('There are ',island,'islands.')
一些细节:
1.堆栈通过python list实现,矩阵是二维list
2.边界条件在代码中有注意。
3.代码运行时,map设置为3x3的(可手动更改,也可以写成输入参数),需自己手动输入0/1