前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >2021-07-28:最短的桥。在给定的二维二进制数组 A 中,存在两座岛。(岛是由四面相连的 1 形成的一个最大组

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

作者头像
福大大架构师每日一题
发布2021-08-05 16:29:51
4900
发布2021-08-05 16:29:51
举报

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

福大大 答案2021-07-28:

宽度优先遍历。找到第一个岛,广播一次,增加一层,碰到第二个岛为止。层数就是需要的返回值。

时间复杂度:O(NM)。

空间复杂度:O(NM)。

代码用golang编写。代码如下:

代码语言:javascript
复制
package main

import (
    "fmt"
    "math"
)

func main() {
    m := [][]int{{0, 1, 0}, {0, 0, 0}, {0, 0, 1}}
    ret := shortestBridge(m)
    fmt.Println(ret)
}

func shortestBridge(m [][]int) int {
    N := len(m)
    M := len(m[0])
    all := N * M
    island := 0
    curs := make([]int, all)
    nexts := make([]int, all)
    records := make([][]int, 2)
    for i := 0; i < 2; i++ {
        records[i] = make([]int, all)
    }
    for i := 0; i < N; i++ {
        for j := 0; j < M; j++ {
            if m[i][j] == 1 { // 当前位置发现了1!
                // 把这一片的1,都变成2,同时,抓上来了,这一片1组成的初始队列
                // curs, 把这一片的1到自己的距离,都设置成1了,records
                queueSize := infect(m, i, j, N, M, curs, 0, records[island])
                V := 1
                for queueSize != 0 {
                    V++
                    // curs里面的点,上下左右,records[点]==0, nexts
                    queueSize = bfs(N, M, all, V, curs, queueSize, nexts, records[island])
                    tmp := curs
                    curs = nexts
                    nexts = tmp
                }
                island++
            }
        }
    }
    min := math.MaxInt64
    for i := 0; i < all; i++ {
        min = getMin(min, records[0][i]+records[1][i])
    }
    return min - 3
}

func getMin(a int, b int) int {
    if a < b {
        return a
    } else {
        return b
    }
}

// 当前来到m[i][j] , 总行数是N,总列数是M
// m[i][j]感染出去(找到这一片岛所有的1),把每一个1的坐标,放入到int[] curs队列!
// 1 (a,b) -> curs[index++] = (a * M + b)
// 1 (c,d) -> curs[index++] = (c * M + d)
// 二维已经变成一维了, 1 (a,b) -> a * M + b
// 设置距离record[a * M +b ] = 1
func infect(m [][]int, i int, j int, N int, M int, curs []int, index int, record []int) int {
    if i < 0 || i == N || j < 0 || j == M || m[i][j] != 1 {
        return index
    }
    // m[i][j] 不越界,且m[i][j] == 1
    m[i][j] = 2
    p := i*M + j
    record[p] = 1
    // 收集到不同的1
    curs[index] = p
    index++
    index = infect(m, i-1, j, N, M, curs, index, record)
    index = infect(m, i+1, j, N, M, curs, index, record)
    index = infect(m, i, j-1, N, M, curs, index, record)
    index = infect(m, i, j+1, N, M, curs, index, record)
    return index
}

// 二维原始矩阵中,N总行数,M总列数
// all 总 all = N * M
// V 要生成的是第几层 curs V-1 nexts V
// record里面拿距离
func bfs(N int, M int, all int, V int, curs []int, size int, nexts []int, record []int) int {
    nexti := 0 // 我要生成的下一层队列成长到哪了?
    for i := 0; i < size; i++ {
        // curs[i] -> 一个位置
        up := twoSelectOne(curs[i] < M, -1, curs[i]-M)
        down := twoSelectOne(curs[i]+M >= all, -1, curs[i]+M)
        left := twoSelectOne(curs[i]%M == 0, -1, curs[i]-1)
        right := twoSelectOne(curs[i]%M == M-1, -1, curs[i]+1)
        if up != -1 && record[up] == 0 {
            record[up] = V
            nexts[nexti] = up
            nexti++
        }
        if down != -1 && record[down] == 0 {
            record[down] = V
            nexts[nexti] = down
            nexti++
        }
        if left != -1 && record[left] == 0 {
            record[left] = V
            nexts[nexti] = left
            nexti++
        }
        if right != -1 && record[right] == 0 {
            record[right] = V
            nexts[nexti] = right
            nexti++
        }
    }
    return nexti
}

func twoSelectOne(c bool, a int, b int) int {
    if c {
        return a
    } else {
        return b
    }
}

执行结果如下:

***

[左神java代码](https://github.com/algorithmzuo/coding-for-great-offer/blob/main/src/class18/Code02_ShortestBridge.java)

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-07-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 福大大架构师每日一题 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档