LeetCode:934. Shortest Bridge - Python

问题描述:

934. 最短的桥

在给定的二维二进制数组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. 1 <= A.length = A[0].length <= 100
  2. 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/
参考链接:参考了别人提交的优秀代码,并做了改进,链接不详。

猜你喜欢

转载自blog.csdn.net/XX_123_1_RJ/article/details/84656064