934. 最短的桥

深度遍历(dfs) 和 广度遍历(bfs) 理解

今天参加LeetCode周赛时候,把我一直不理解的dfsbfs搞懂了,真的开心!相信我,搞懂我下面这道题,这个概念就理解了!

解释

**dfs:**一条路走的死,用栈实现,进栈、退栈,一搜到底!一般用递归实现

bfs: 辐射八方,用队实现,入队、出队,步步为营!一般用迭代实现

举例

最短的桥

在给定的二维二进制数组 A 中,存在两座岛。(岛是由四面相连的 1 形成的一个最大组。)
现在,我们可以将 0 变为 1,以使两座岛连接起来,变成一座岛。
返回必须翻转的 0 的最小数目。(可以保证答案至少是 1。)

例子:

输入:[[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. 先找到其中一个岛(染色,我会用dfs和bfs分别实现)
  2. 再找到另一个岛,从这个岛中,任意位置出发,首先碰到第一个岛就是最小值,所以可以用bfs,意思这些岛中点一起出发,看谁先碰到另一个岛,返回最小值

** 用dfs染色 ,找到一个岛屿**

visited1 = set()
def dfs(i,j):
    A[i][j] = 2
    visited1.add((i,j))
    if i> 0 and (i-1,j) not in visited1 and A[i-1][j] == 1:
        dfs(i-1,j)
        visited1.add((i-1,j))
    if i < row-1 and (i+1,j) not in visited1 and A[i+1][j] == 1:
        dfs(i+1,j)
        visited1.add((i+1,j))
    if j > 0 and (i,j-1) not in visited1 and A[i][j-1] == 1:
        dfs(i,j-1)
        visited1.add((i,j-1))
    if j < col-1 and (i,j+1) not in visited1 and A[i][j+1] == 1:
        dfs(i,j+1)
        visited1.add((i,j+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]]

经过dfs:,A:[[2, 2, 2, 2, 2], [2, 0, 0, 0, 2], [2, 0, 1, 0, 2], [2, 0, 0, 0, 2], [2, 2, 2, 2, 2]]

def bfs(i,j):
    queue = [(i,j)]
    visited = set((i,j))
    while queue:
        i,j = queue.pop(0)
        A[i][j] = 2
        if i>0 and (i-1,j) not in visited and A[i-1][j] == 1:
            queue.append((i-1,j))
            visited.add((i-1,j))
        if i < row-1 and (i+1,j) not in visited  and A[i+1][j] == 1:
            queue.append((i+1,j))
            visited.add((i+1,j))
        if j > 0 and (i,j-1) not in visited and A[i][j-1] == 1:
            queue.append((i,j-1))
            visited.add((i,j-1))
        if j < col-1 and (i,j+1) not in visited and A[i][j+1] == 1:
            queue.append((i,j+1))
            visited.add((i,j+1))
a = Solution()
print(a.shortestBridge([[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]]))

刚开始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]]

经过bfs:,A:[[2, 2, 2, 2, 2], [2, 0, 0, 0, 2], [2, 0, 1, 0, 2], [2, 0, 0, 0, 2], [2, 2, 2, 2, 2]]

所以,
染色成功!

#  找一个岛
queue = []
visited2 = set()
for i in range(row):
    for j in range(col):
        if A[i][j] == 1:
            # 位置i,j 和 step = 0
            queue.append((i,j,0))
            visited2.add((i,j))     

接下来,

    # bfs 找一个岛到另一个岛最小值
while queue:
    i,j,step = queue.pop(0)
    if (i>0 and A[i-1][j] == 2) or (i<row-1 and A[i+1][j] == 2) \
            or ( j > 0 and A[i][j-1] == 2) or (j<col-1 and A[i][j+1]==2):
        return step
    if i > 0 and (i-1,j) not in visited1 and A[i-1][j] == 0:
        queue.append((i-1,j,step+1))
        visited1.add((i-1,j))
    if i < row -1 and (i+1,j) not in visited1 and A[i+1][j] == 0:
        queue.append((i+1,j,step+1))
        visited1.add((i+1,j))
    if j > 0 and (i,j-1) not in visited1 and A[i][j-1] == 0:
        queue.append((i,j-1,step+1))
        visited1.add((i,j-1))
    if j < col-1 and (i,j+1) not in visited1 and A[i][j+1] == 0:
        queue.append((i,j+1,step+1))
        visited1.add((i,j+1))

结果

a = Solution()
print(a.shortestBridge([[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

附上完整代码

class Solution(object):
    def shortestBridge(self, A):
        """
        :type A: List[List[int]]
        :rtype: int
        """
        # 行 和 列
        row = len(A)
        col = len(A[0])
        """
        我分别用dfs和bfs把其中一个岛染成2(一开始是1)
        """
        # 记录已经访问的点
        visited1 = set()
        def dfs(i,j):
            A[i][j] = 2
            visited1.add((i,j))
            if i> 0 and (i-1,j) not in visited1 and A[i-1][j] == 1:
                dfs(i-1,j)
                visited1.add((i-1,j))
            if i < row-1 and (i+1,j) not in visited1 and A[i+1][j] == 1:
                dfs(i+1,j)
                visited1.add((i+1,j))
            if j > 0 and (i,j-1) not in visited1 and A[i][j-1] == 1:
                dfs(i,j-1)
                visited1.add((i,j-1))
            if j < col-1 and (i,j+1) not in visited1 and A[i][j+1] == 1:
                dfs(i,j+1)
                visited1.add((i,j+1))
        def bfs(i,j):
            queue = [(i,j)]
            visited = set((i,j))
            while queue:
                i,j = queue.pop(0)
                A[i][j] = 2
                if i>0 and (i-1,j) not in visited and A[i-1][j] == 1:
                    queue.append((i-1,j))
                    visited.add((i-1,j))
                if i < row-1 and (i+1,j) not in visited  and A[i+1][j] == 1:
                    queue.append((i+1,j))
                    visited.add((i+1,j))
                if j > 0 and (i,j-1) not in visited and A[i][j-1] == 1:
                    queue.append((i,j-1))
                    visited.add((i,j-1))
                if j < col-1 and (i,j+1) not in visited and A[i][j+1] == 1:
                    queue.append((i,j+1))
                    visited.add((i,j+1)) 
        # 保证只找到一个岛
        flag = False
        for i in range(row):
            if flag:
                break
            for j in range(col):
                if A[i][j] == 1:
                    # dfs
#                     dfs(i,j)
#                     flag = True
#                     break
                    # bfs
                    bfs(i,j)
                    flag = True
                    break
#         print("dfs:",A)
#         print("bfs:",A)
        # 下面开始找另一个岛,把位置放入队列,用bfs找它离上一个岛最小距离
        queue = []
        visited2 = set()
        for i in range(row):
            for j in range(col):
                if A[i][j] == 1:
                    # 位置i,j 和 step = 0
                    queue.append((i,j,0))
                    visited2.add((i,j))
        # 用bfs
        while queue:
            i,j,step = queue.pop(0)
            if (i>0 and A[i-1][j] == 2) or (i<row-1 and A[i+1][j] == 2) \
                    or ( j > 0 and A[i][j-1] == 2) or (j<col-1 and A[i][j+1]==2):
                return step
            if i > 0 and (i-1,j) not in visited1 and A[i-1][j] == 0:
                queue.append((i-1,j,step+1))
                visited1.add((i-1,j))
            if i < row -1 and (i+1,j) not in visited1 and A[i+1][j] == 0:
                queue.append((i+1,j,step+1))
                visited1.add((i+1,j))
            if j > 0 and (i,j-1) not in visited1 and A[i][j-1] == 0:
                queue.append((i,j-1,step+1))
                visited1.add((i,j-1))
            if j < col-1 and (i,j+1) not in visited1 and A[i][j+1] == 0:
                queue.append((i,j+1,step+1))
                visited1.add((i,j+1))
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值