问题描述:
在给定的二维二进制数组A
中,存在两座岛。(岛是由四面相连的1
形成的一个最大组)
现在,我们可以将0
变为1
,以使两座岛连接起来,变成一座岛。
返回必须翻转的 0
的最小数目。(可以保证答案至少是1
)
示例 1:
输入:[[0,1],[1,0]]
输出:1
示例 2:
输入:[[0,1,0],[0,0,0],[0,0,1]]
输出:2
示例 3:
输入:[[1,1,1,1,1],[1,0,0,0,1],[1,0,1,0,1],[1,0,0,0,1],[1,1,1,1,1]]
输出:1
提示:
1 <= A.length = A[0].length <= 100
A[i][j] == 0 或 A[i][j] == 1
问题分析:
这个题目比较有意思,这几天遇到的一个比较有意思的题目了。一眼看过去,基本可以想到用广度优先搜索来解决,但是很快就会意识到到一个问题。那就是,如果是点到点的搜索,很好实现,那现在是一个团(岛)到另外一个团(岛)的搜索,如何实现?其实还好,可以把一个团(岛)作为一个点(这一个大团(岛),可以用遍历操作,即每次遍历一个团(到),向外扩展),进行搜索。
(1)先找到一个小岛,可以遍历 A
找到一个点,以这个点为基础,广度优先搜索或者深度优先搜索,找到这个岛全部位置(放到一个队列 start
里面),这里,我更喜欢广度优先搜索法,简单好理解。
(2)以(1)中的队列 start
为基础,广度优先搜索,向外一层一层地扩展,每扩展一层,就更新一下 start
,就是始终让它保持是一个最外层边界,直到它接触到另外一个岛。
(3)在(2)中,向外扩展的过程中,不要忘记,记录扩展了几次,这也是求得最小距离的过程。
Python3实现:
# @Time :2018/12/01
# @Author :LiuYinxing
# 广度优先搜索
class Solution:
def shortestBridge(self, A):
row, col = len(A), len(A[0])
visited = [[0] * col for _ in range(row)] # 负责记录其中的一个岛
q = []
start = [] # 保存其中一个岛的所有位置
found = False
for i in range(row): # 先找到一个岛中其中一个位置
for j in range(col):
if A[i][j] == 1:
found = True
q.append((i, j))
visited[i][j] = 1
break
if found:
break
while q: # 以其中一个岛的位置为基础,使用广度优先搜索方法,继续找到这个岛的其他位置
tmp = []
for a in q:
x, y = a[0], a[1]
start.append(a) # 把岛的位置放到 start 队列里面
if (x - 1 >= 0) and (visited[x - 1][y] == 0) and (A[x - 1][y] == 1):
tmp.append((x - 1, y))
visited[x - 1][y] = 1
if (x + 1 < col) and (visited[x + 1][y] == 0) and (A[x + 1][y] == 1):
tmp.append((x + 1, y))
visited[x + 1][y] = 1
if (y - 1 >= 0) and (visited[x][y - 1] == 0) and (A[x][y - 1] == 1):
tmp.append((x, y - 1))
visited[x][y - 1] = 1
if (y + 1 < row) and (visited[x][y + 1] == 0) and (A[x][y + 1] == 1):
tmp.append((x, y + 1))
visited[x][y + 1] = 1
q = tmp
ans = 0
while start: # 从一个岛出发,去找探索另外一个岛
tmp = []
for a in start: # 广度优先算法,一层一层的探查 是否 到达另外一个岛
x, y = a[0], a[1]
if (x - 1 >= 0) and (visited[x - 1][y] == 0):
if A[x - 1][y] == 1:
return ans
else:
tmp.append((x - 1, y))
visited[x - 1][y] = 1
if (x + 1 < col) and (visited[x + 1][y] == 0):
if A[x + 1][y] == 1:
return ans
else:
tmp.append((x + 1, y))
visited[x + 1][y] = 1
if (y - 1 >= 0) and (visited[x][y - 1] == 0):
if A[x][y - 1] == 1:
return ans
else:
tmp.append((x, y - 1))
visited[x][y - 1] = 1
if (y + 1 < row) and (visited[x][y + 1] == 0):
if A[x][y+1] == 1:
return ans
else:
tmp.append((x, y + 1))
visited[x][y + 1] = 1
start = tmp # 探索了一层之后,没有发现另外一个岛,则,更新 最外层边界 以及 路径长度
ans += 1
return ans
if __name__ == '__main__':
A = [[1, 1, 1, 1, 1],
[1, 0, 0, 0, 1],
[1, 0, 1, 0, 1],
[1, 0, 0, 0, 1],
[1, 1, 1, 1, 1]]
print(Solution().shortestBridge(A))
声明: 总结学习,有问题或不妥之处,可以批评指正哦。
题目链接:leetcode-cn.com/problems/shortest-bridge/
参考链接:参考了别人提交的优秀代码,并做了改进,链接不详。