1. 问题描述:
在给定的二维二进制数组 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
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/shortest-bridge
2. 思路分析:
① 分析题目可以知道这道题目类似于之前的岛屿题目,所以我的第一反应应该需要使用到dfs,一个比较容易想到的做法是从第一个岛屿的边缘出发,然后寻找到达第二个岛屿的最短路径,基于这个想法我们可以想到使用dfs搜索第一个岛屿,并且将这些岛屿对应的位置进行标记,可以修改为2或者是其他的数字,在岛屿中进行标记之后就可以从这些位置出发寻找最短路径,因为是从某个点出发到终点的最短路径所以根据起点到终点的最短路径这个特点想到使用bfs进行搜索
② 基于①中的思路,具体的做法如下:
(1) 使用dfs标记第一个岛屿的位置为2,并且使用双端队列来记录这些标记的位置,因为使用的是python语言,所以可以使用collections.deque()声明一个双端队列,队列的元素为元组类型这样可以标记图中二维的坐标位置
(2) bfs搜索:当队列不为空的时候执行循环,对于当前队列中的所有元素,尝试搜索上下左右四个方向,当这些位置为0的时候那么就可以标记为2,并且将这些值为0的位置加入到队列中这样可以进行下一次的循环,当执行完队列中所有的操作之后那么步数肯定是加1的,然后执行队列元素的下一次循环,其实这个过程相当于是第一个岛屿的的每一个边缘都向迈出自己的一步然后继续执行这样的操作最后看哪一个先到达最终那么先到达终点的路径肯定是最小的
3. 代码如下:
import collections
from typing import List
class Solution:
def dfs(self, A: List[List[int]], x: int, y: int, queue: collections.deque, pos: List[List[int]]):
# 搜索岛屿的时候对位置进行标记
A[x][y] = 2
# 将第一个岛屿的所有坐标加入到队列中
queue.append((x, y))
for i in range(4):
x1, y1 = x + pos[i][0], y + pos[i][1]
if 0 <= x1 < len(A) and 0 <= y1 < len(A[0]) and A[x1][y1] == 1:
self.dfs(A, x1, y1, queue, pos)
def bfs(self, A: List[List[int]], x: int, y: int, queue: collections.deque, pos: List[List[int]]):
step = 0
while queue:
size = len(queue)
for i in range(size):
poll = queue.popleft()
for j in range(4):
x1, y1 = poll[0] + pos[j][0], poll[1] + pos[j][1]
if 0 <= x1 < len(A) and 0 <= y1 < len(A[0]) and A[x1][y1] == 2: continue
if 0 <= x1 < len(A) and 0 <= y1 < len(A[0]) and A[x1][y1] == 1:
return step
if 0 <= x1 < len(A) and 0 <= y1 < len(A[0]) and A[x1][y1] == 0:
A[x1][y1] = 2
queue.append((x1, y1))
step += 1
def shortestBridge(self, A: List[List[int]]) -> int:
i, j = 0, 0
# 右左上下四个方向
pos = [[0, 1], [0, -1], [1, 0], [-1, 0]]
queue = collections.deque()
while i < len(A):
while j < len(A[0]):
if A[i][j] == 1:
# 使用dfs搜索标记第一个岛屿
self.dfs(A, i, j, queue, pos)
return self.bfs(A, i, j, queue, pos)
j += 1
j = 0
i += 1