首页 > 其他分享 >【搜索】力扣934:最短的桥

【搜索】力扣934:最短的桥

时间:2022-08-16 23:00:50浏览次数:85  
标签:deque nx int List 最短 力扣 ny BFS 934

在给定的二维二进制数组 A 中,存在两座岛。(岛是由四面相连的 1 形成的一个最大组。)

现在,我们可以将 0 变为 1,以使两座岛连接起来,变成一座岛。

返回必须翻转的 0 的最小数目。(可以保证答案至少是 1 。)

示例:

输入: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]]
输出:1

很有意思的题

总体思路:首先找到这两座岛,然后选择其中一座,将它不断向外延伸一圈填海造陆,直到到达另一座岛。

BFS 常用来处理最短路径问题或可达性问题。

DFS + BFS

先 dfs 找到其中一个岛,然后 bfs 找第二个岛

  • 在寻找第一座岛时,使用深度优先搜索
  • 在向外延伸时,使用广度优先搜索

具体地:

  • 遍历矩阵,找到的一个 1,调用dfs把和 1 联通的所有 1 改为 2,也就是识别出这整座岛,与另一座岛屿进行区分,也防止重复遍历。同时利用双端队列 queue 存储第一个岛

  • 调用bfs从第一个岛开始逐层向外“填海造陆”(即把它把周围的 0 改为 2 ),直到在某次扩散时遇到 1,说明已经遇到了另一个岛,此时返回扩散的次数即可

image
来源:https://leetcode.cn/problems/shortest-bridge/solution/bfs-tian-hai-zao-lu-ti-jie-si-lu-by-carp-6w8j/

from collections import deque
class Solution:
    def shortestBridge(self, A: List[List[int]]) -> int:
        m, n = len(A), len(A[0])
        directions = [(-1,0), (1,0), (0,-1), (0,1)] # 方向数组
        q = collections.deque()
        step = 0 # 要返回的结果

        # 通过dfs查找第一个岛,并且标记为已访问,也就是将 1 变为 2
        def dfs(i, j):
            if not 0 <= i < m or not 0 <= j < n or A[i][j] == 0 or A[i][j] == 2:
                return
            # A[i][j] == 1 的情况,标记并加入队列,搜索周围
            A[i][j] = 2
            q.append((i, j))
            for x, y in directions:
                ni, nj = i + x, j + y
                dfs(ni, nj)

        find = False
        for i in range(m):
            for j in range(n):
                if A[i][j] == 1 and not find:
                    dfs(i, j)
                    find = True

        # bfs # 从找到的岛开始扩展,把过程中已访问的 0 变为 2,每扩展一层,step +1
        while q:
            size = len(q)
            for _ in range(size):
                i, j = q.popleft()
                for x, y in directions:
                    ni, nj = i + x, j + y
                    if not 0 <= ni < m or not 0 <= nj < n or A[ni][nj] == 2:
                        continue
                    if A[ni][nj] == 1:
                        return step
                    # else: 也就是 A[ni][nj] == 0 的情况,标记
                    A[ni][nj] = 2
                    q.append((ni, nj))
            step += 1

        return step

时间复杂度:O(MN),其中 M 和 N 分别是数组 A 的行数和列数。
空间复杂度:O(MN)。

BFS + BFS

新建标记矩阵

先找到一个整体的 1,然后再探查另一个岛上的 1。

from collections import deque
class Solution:
    def shortestBridge(self, A: List[List[int]]) -> int:
        m, n = len(A), len(A[0])
        directions = [(-1,0), (1,0), (0,-1), (0,1)]
        visited = [[False] * n for _ in range(m)] # 标记数组

        def bfs(i,j):
            q = collections.deque([(i, j, 0)])
            while q:
                x, y, time = q.popleft()
                for dx, dy in directions:
                    nx, ny = x + dx, y + dy
                    if nx >= 0 and nx < m and ny >= 0 and ny < n and visited[nx][ny] == False:
                        visited[nx][ny] = True
                        if A[nx][ny] == 1:
                            if time >= 1: # 通过跨越 0 找到了另一座岛
                                return time
                            else: # time 为 0 表示此时还是在同一座岛屿,记得左插,优先级大于 0 的块
                                q.appendleft((nx,ny,0))
                        else:
                            q.append((nx, ny, time + 1))
        # 找到第一个为 1 的点
        for i in range(m):
            for j in range(n):
                if A[i][j] == 1:
                    visited[i][j] = True
                    return bfs(i,j)


作者:linn-9k
链接:https://leetcode.cn/problems/shortest-bridge/solution/si-lu-bi-jiao-qing-xi-de-01bfs-by-linn-9-r0vu/

改变矩阵,使用数字标记(最佳)

先用BFS把一个岛全部标成 0 并同时加入另一个队列。 然后从这个队列出发进行BFS,直到找到一个陆地。

from collections import deque
class Solution:
    def shortestBridge(self, A: List[List[int]]) -> int:
        directions = [(0,1),(0,-1),(1,0),(-1,0)]
        n = len(grid)

        q = deque()
        ql = deque()
        i = 0
        while not q:
            for j in range(n):
                if A[i][j] == 1:
                    q.append((i,j))
                    ql.append((i,j))
                    A[i][j] = 0
                    break
            i += 1

        while ql:
            i, j = ql.popleft()
            for d in directions:
                x, y = i + d[0], j + d[1]
                if 0 <= x < n and 0 <= y < n and A[x][y]:
                    q.append((x, y))
                    ql.append((x, y))
                    A[x][y] = 0

        step = 0
        visited = set(list(q))
        while q:
            w = len(q)
            for k in range(w):
                i, j = q.popleft()
                for d in directions:
                    x, y = i + d[0], j + d[1]
                    if 0 <= x < n and 0 <= y < n and (x, y) not in visited:
                        if A[x][y]:
                            return step
                        q.append((x, y))
                        visited.add((x, y))
            step += 1

标签:deque,nx,int,List,最短,力扣,ny,BFS,934
From: https://www.cnblogs.com/Jojo-L/p/16592042.html

相关文章

  • 力扣-刷题-324. 摆动排序 II
    题目链接来源:力扣(LeetCode)链接:https://leetcode.cn/problems/wiggle-sort-ii著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。题目描述给你一个......
  • 力扣-88-合并两个有序数组
    本来觉得很简单,然后准备提交了发现要在数组1里面合并,没有额外空间然后就有了一个大胆的想法——我直接插进去然后sortclassSolution{public: voidmerge(vector<int>......
  • 力扣练习——70 串联所有单词的子串
    1.问题描述给定一个字符串s和一些长度相同的单词words。找出s中恰好可以由words中所有单词串联形成的子串的起始位置。注意子串要与words中的单词完全匹配,中间......
  • 力扣练习——69 前K个高频单词
    1.问题描述给一非空的单词列表,返回前k个出现次数最多的单词。返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率,按字母顺序排序。 示例1:......
  • 力扣 101. 对称二叉树
    101.对称二叉树给你一个二叉树的根节点 root ,检查它是否轴对称。示例1:输入:root=[1,2,2,3,4,4,3]输出:true示例2:输入:root=[1,2,2,null,3,null,3]输......
  • 力扣 100.相同的数
    100.相同的树给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。 示......
  • CF464E The Classic Problem(线段树 最短路)
    CF464ETheClassicProblem\(\bigstar\texttt{Hint}\):发现没有什么好的突破口?为什么不想想怎样才能实现题目中\(2^x\)的加减法呢?可见每次加减法,我们要做的是将添加的......
  • 力扣233(java)-数字1的个数(困难)
    题目:给定一个整数n,计算所有小于等于n的非负整数中数字1出现的个数。 示例1:输入:n=13输出:6示例2:输入:n=0输出:0 提示:0<=n<=109来源:力扣(LeetCode)链接:h......
  • 牛客小白月赛54 D-Word(最短路/bfs)
    链接:https://ac.nowcoder.com/acm/contest/38457/D题目描述给你一个包含n个单词的单词表。你需要将单词s以如下操作转换成t。每次改变s的一个字母。你需要保证......