NO.3 Leetcode刷题 934. 最短的桥(python)

题目:给你一个大小为 n x n 的二元矩阵 grid ,其中 1 表示陆地,0 表示水域。岛是由四面相连的 1 形成的一个最大组,即不会与非组内的任何其他 1 相连。grid 中 恰好存在两座岛 。你可以将任意数量的 0 变为 1 ,以使两座岛连接起来,变成 一座岛 。返回必须翻转的 0 的最小数目。

示例 1:

输入:grid = [[0,1],[1,0]]
输出:1


示例 2:

输入:grid = [[0,1,0],[0,0,0],[0,0,1]]
输出:2


示例 3:

输入:grid = [[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

解题思路:广度优先搜索(BFS)
        题目中求最少的翻转 0 的数目等价于求矩阵中两个岛的最短距离,因此我们可以广度优先搜索来找到矩阵中两个块的最短距离。首先找到其中一座岛,然后将其不断向外延伸一圈,直到到达了另一座岛,延伸的圈数即为最短距离。广度优先搜索时,我们可以将已经遍历过的位置标记为−1,实际计算过程如下:

  • 我们通过遍历找到数组grid 中的 1后进行广度优先搜索,此时可以得到第一座岛的位置集合,记为island,并将其位置全部标记为−1。
  •  随后我们从island 中的所有位置开始进行广度优先搜索,当它们到达了任意的1 时,即表示搜索到了第二个岛,搜索的层数就是答案。
class Solution:
    def shortestBridge(self, grid: List[List[int]]) -> int:
        n = len(grid)       
        for i, row in enumerate(grid):
            # 第一次从数组中的1开始广度搜索第一座岛的位置集合,并将遍历后的位置标记为-1
            for j, v in enumerate(row):
                # 如果遍历到水域,则跳过本次遍历
                if v != 1:
                    continue
                island = [] # 定义island数组用于存放第一座岛的位置集合
                grid[i][j] = -1 # 将搜索到的岛的位置集合标记为-1
                q = deque([(i, j)]) # 定义一个双向队列
                # 如果队列中含有元素则进行搜索,直到最后队列为空,跳出搜索
                while q:
                    x, y = q.popleft() # 从队列中拿出一个元素
                    island.append((x, y)) # 将该元素存放到岛中
                    # 遍历该元素的邻近元素
                    for nx, ny in (x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1):
                        # 判断遍历是否超出数组范围及邻近元素是否为第一座岛的集合
                        if 0 <= nx < n and 0 <= ny < n and grid[nx][ny] == 1:
                            grid[nx][ny] = -1 # 搜索到的岛的位置集合标记为-1
                            q.append((nx, ny))# 将邻近的满足岛集合的元素添加到队列

                step = 0 # 定义变量step存放最短桥的距离
                q = island # 将岛中集合存放到队列
                # 第二次从第一座岛的所有位置开始广度搜索,当搜索到1时,即表示找到了第二座岛,返回step
                while True:
                    # 将岛的位置集合赋予给tmp,若第一次搜索完仍没有找到第二座岛
                    # 则之后tmp为上一次搜索完后所标记为-1的位置集合
                    tmp = q 
                    q = [] # 初始化辅助队列为空
                    # 从第一座岛的所有位置开始广度搜索
                    for x, y in tmp:
                        # 遍历邻近元素
                        for nx, ny in (x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1):
                            # 判断遍历是否超出数组范围
                            if 0 <= nx < n and 0 <= ny < n:
                                # 搜索到1则表示找到第二座岛,
                                if grid[nx][ny] == 1:
                                    return step
                                    # 搜索到0则标记为1并添加到队列中
                                if grid[nx][ny] == 0:
                                    grid[nx][ny] = -1
                                    q.append((nx, ny))
                    step += 1

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python LeetCode刷题指南是一个帮助想要提高他们算法和编程能力的人通过LeetCode平台进行刷题的指南。以下是一些建议和步骤: 1. 建立良好的编程基础:在开始之前,确保你对Python编程语言有一定的了解,并掌握基本的数据结构和算法知识,比如链表、栈、队列、二叉树等。 2. 熟悉LeetCode题库:花一些时间浏览LeetCode题库,了解不同题目的分类和难度等级。这样你就能更好地规划你的刷题计划。 3. 制定计划和目标:根据你自己的时间和目标,设置一个刷题计划。计划可以包括每天刷多少题目、每周完成的目标等。通过制定计划,你可以更有条理地刷题,并逐渐提高自己的能力。 4. 解题思路和算法:在开始解题之前,先仔细阅读题目,理解题意和要求。然后,考虑适合该问题的算法和数据结构。在LeetCode网站上,每个问题都有详细的解题思路和讨论,可以从中获得灵感。 5. 编码和调试:根据你选择的算法和数据结构,使用Python编写解决方案。在编码过程中,注重代码的可读性和可维护性。完成后,运行代码进行测试并调试。 6. 提交和优化:在完成一个问题的解答后,提交你的解答并查看运行结果。如果通过所有的测试用例,那么恭喜你!如果没有通过,仔细检查代码并修改错误。同时,尝试优化你的解法,使其更高效。 7. 学习和总结:刷题是一个学习和成长的过程。通过刷题,你会遇到不同的问题和挑战,学会更多的算法和技巧。每个完成的题目都对你的编程能力有所增加,不论是通过自己的思考还是学习他人的解法。完成一个问题后,不要忘记总结并思考这个问题的解题思路和优化方法。 总之,Python LeetCode刷题指南提醒我们刷题不仅仅是为了解决具体问题,更是为了提升我们的算法和编程能力。通过系统化的刷题计划和总结,我们可以逐渐掌握更多的算法和数据结构,并在实际项目中得以应用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值