首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >2021-07-28:最短的桥。在给定的二维二进制数组 A 中,存

2021-07-28:最短的桥。在给定的二维二进制数组 A 中,存

原创
作者头像
福大大架构师每日一题
修改于 2021-07-29 02:41:47
修改于 2021-07-29 02:41:47
4110
举报

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

福大大 答案2021-07-28:

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

时间复杂度:O(NM)。

空间复杂度:O(NM)。

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

代码语言:txt
AI代码解释
复制
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代码

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
2021-12-28:给定一个二维数组matrix,matrix[i][j] = k代
从(i,j)位置可以随意往右跳<=k步,或者从(i,j)位置可以随意往下跳<=k步,
福大大架构师每日一题
2021/12/28
2850
2023-05-07:给你一个大小为 n x n 二进制矩阵 grid 。最多 只能将一格 0 变成 1 。 返回执行此操作后,grid 中最大的岛屿面积是多少
2023-05-07:给你一个大小为 n x n 二进制矩阵 grid 。最多 只能将一格 0 变成 1 。
福大大架构师每日一题
2023/05/07
4190
2023-05-07:给你一个大小为 n x n 二进制矩阵 grid 。最多 只能将一格 0 变成 1 。 返回执行此操作后,grid 中最大的岛屿面积是多少
2021-07-17:一个不含有负数的数组可以代表一圈环形山,每
2021-07-17:一个不含有负数的数组可以代表一圈环形山,每个位置的值代表山的高度。比如, {3,1,2,4,5}、{4,5,3,1,2}或{1,2,4,5,3}都代表同样结构的环形山。山峰A和山峰B能够相互看见的条件为: 1.如果A和B是同一座山,认为不能相互看见,2.如果A和B是不同的山,并且在环中相邻,认为可以相互看见,3.如果A和B是不同的山,并且在环中不相邻,假设两座山高度的最小值为min,1)如果A通过顺时针方向到B的途中没有高度比min大的山峰,认为A和B可以相互看见,2)如果A通过逆时针方向到B的途中没有高度比min大的山峰,认为A和B可以相互看见。两个方向只要有一个能看见,就算A和B可以相互看见。给定一个不含有负数且没有重复值的数组 arr,请返回有多少对山峰能够相互看见。进阶问题:给定一个不含有负数但可能含有重复值的数组arr,返回有多少对山峰能够相互看见。
福大大架构师每日一题
2021/07/17
2060
2021-07-17:一个不含有负数的数组可以代表一圈环形山,每
2021-08-07:与数组中元素的最大异或值。给你一个由非负
2021-08-07:与数组中元素的最大异或值。给你一个由非负整数组成的数组 nums 。另有一个查询数组 queries ,其中 queriesi = xi, mi 。第 i 个查询的答案是 xi 和任何 nums 数组中不超过 mi 的元素按位异或(XOR)得到的最大值。换句话说,答案是 max(numsj XOR xi) ,其中所有 j 均满足 numsj <= mi 。如果 nums 中的所有元素都大于 mi,最终答案就是 -1 。返回一个整数数组 answer 作为查询的答案,其中 answer.length == queries.length 且 answeri 是第 i 个查询的答案。
福大大架构师每日一题
2021/08/07
3050
2021-08-07:与数组中元素的最大异或值。给你一个由非负
2021-08-16:回文对。给定一组 互不相同 的单词, 找出所
2021-08-16:回文对。给定一组 互不相同 的单词, 找出所有 不同 的索引对 (i, j),使得列表中的两个单词, wordsi + wordsj ,可拼接成回文串。
福大大架构师每日一题
2021/08/16
2470
2021-08-16:回文对。给定一组 互不相同 的单词, 找出所
2021-04-27:如果一个字符相邻的位置没有相同字符
2021-04-27:如果一个字符相邻的位置没有相同字符,那么这个位置的字符出现不能被消掉。比如:"ab",其中a和b都不能被消掉 。如果一个字符相邻的位置有相同字符,就可以一起消掉。比如:“abbbc”,中间一串的b是可以被消掉的, 消除之后剩下“ac”。某些字符如果消掉了,剩下的字符认为重新靠在一起。给定一个字符串,你可以决定每一步消除的顺序,目标是请尽可能多的消掉字符,返回最少的剩余字符数量。比如:"aacca", 如果先消掉最左侧的"aa",那么将剩下"cca",然后把"cc"消掉,剩下的"a"将无法再消除,返回1。但是如果先消掉中间的"cc",那么将剩下"aaa",最后都消掉就一个字符也不剩了,返回0,这才是最优解。 再比如:"baaccabb",如果先消除最左侧的两个a,剩下"bccabb",如果再消除最左侧的两个c,剩下"babb", 最后消除最右侧的两个b,剩下"ba"无法再消除,返回2。而最优策略是:先消除中间的两个c,剩下"baaabb",再消除中间的三个a,剩下"bbb",最后消除三个b, 不留下任何字符,返回0,这才是最优解。
福大大架构师每日一题
2021/05/04
4930
2021-04-27:如果一个字符相邻的位置没有相同字符
2021-04-30:一条直线上有居民点,邮局只能建在居民点上。给定一个有序正数数组arr
2021-04-30:一条直线上有居民点,邮局只能建在居民点上。给定一个有序正数数组arr,每个值表示 居民点的一维坐标,再给定一个正数 num,表示邮局数量。选择num个居民点建立num个 邮局,使所有的居民点到最近邮局的总距离最短,返回最短的总距离。【举例】arr=1,2,3,4,5,1000,num=2。第一个邮局建立在 3 位置,第二个邮局建立在 1000 位置。那么 1 位置到邮局的距离 为 2, 2 位置到邮局距离为 1,3 位置到邮局的距离为 0,4 位置到邮局的距离为 1, 5 位置到邮局的距 离为 2,1000 位置到邮局的距离为 0。这种方案下的总距离为 6, 其他任何方案的总距离都不会 比该方案的总距离更短,所以返回6。
福大大架构师每日一题
2021/05/04
5030
2021-04-30:一条直线上有居民点,邮局只能建在居民点上。给定一个有序正数数组arr
2021-05-20:给定一个数组arr, 返回如果排序之后,相邻两数
2021-05-20:给定一个数组arr, 返回如果排序之后,相邻两数的最大差值。要求:时间复杂度O(N) 。
福大大架构师每日一题
2021/05/20
3650
2021-05-20:给定一个数组arr, 返回如果排序之后,相邻两数
​2021-05-14:给定一个数组arr,想知道arr中哪两个数的异或结果最大。
2021-05-14:给定一个数组arr,想知道arr中哪两个数的异或结果最大。返回最大的异或结果。
福大大架构师每日一题
2021/05/14
5670
​2021-05-14:给定一个数组arr,想知道arr中哪两个数的异或结果最大。
2021-09-05:单词搜索 II。给定一个 m x n 二维字符网格 bo
2021-09-05:单词搜索 II。给定一个 m x n 二维字符网格 board 和一个单词(字符串)列表 words,找出所有同时在二维网格和字典中出现的单词。单词必须按照字母顺序,通过 相邻的单元格 内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。力扣212。
福大大架构师每日一题
2021/09/05
2860
2025-01-27:包含所有 1 的最小矩形面积Ⅱ。用go语言,给定一个二维二进制数组,找到三个非重叠且面积非零的矩形,这三个
2025-01-27:包含所有 1 的最小矩形面积Ⅱ。用go语言,给定一个二维二进制数组,找到三个非重叠且面积非零的矩形,这三个矩形在水平和垂直方向上覆盖了数组中的所有1,返回这三个矩形的面积之和的最小值。这些矩形可以相互接触。
福大大架构师每日一题
2025/02/05
830
2025-01-27:包含所有 1 的最小矩形面积Ⅱ。用go语言,给定一个二维二进制数组,找到三个非重叠且面积非零的矩形,这三个
2021-04-03:给定两个字符串str1和str2,想把str2整体插入到str1中的某个
2021-04-03:给定两个字符串str1和str2,想把str2整体插入到str1中的某个位置,形成最大的字典序,返回字典序最大的结果。
福大大架构师每日一题
2021/04/03
5720
2021-04-03:给定两个字符串str1和str2,想把str2整体插入到str1中的某个
2021-06-26:给定一个只有0和1组成的二维数组,返回边框全是1的最大正方形面积。
2021-06-26:给定一个只有0和1组成的二维数组,返回边框全是1的最大正方形面积。
福大大架构师每日一题
2021/06/26
4420
2021-06-26:给定一个只有0和1组成的二维数组,返回边框全是1的最大正方形面积。
2021-07-30:两个有序数组间相加和的Topk问题。给定两个
2021-07-30:两个有序数组间相加和的Topk问题。给定两个有序数组arr1和arr2,再给定一个整数k,返回来自arr1和arr2的两个数相加和最大的前k个,两个数必须分别来自两个数组。按照降序输出。要求时间复杂度为O(klogk)。
福大大架构师每日一题
2021/07/31
3550
2021-07-30:两个有序数组间相加和的Topk问题。给定两个
2021-10-26:给定一个数组arr,arr[i] = j,表示第i号试题的
2021-10-26:给定一个数组arr,arri = j,表示第i号试题的难度为j。给定一个非负数M。想出一张卷子,对于任何相邻的两道题目,前一题的难度不能超过后一题的难度+M。返回所有可能的卷子种数。
福大大架构师每日一题
2021/10/26
3320
2021-04-18:给定一个二维数组matrix,里面的值不是1就是0,
2021-04-18:给定一个二维数组matrix,里面的值不是1就是0,上、下、左、右相邻的1认为是一片岛,返回matrix中岛的数量。
福大大架构师每日一题
2021/05/04
4230
2021-04-18:给定一个二维数组matrix,里面的值不是1就是0,
2023-07-20:假设一共有M个车库,编号1~M,时间点从早到晚是从1~T, 一共有N个记录,每一条记录如下{a, b, c
2023-07-20:假设一共有M个车库,编号1 ~ M,时间点从早到晚是从1 ~ T,
福大大架构师每日一题
2023/07/25
2930
2023-07-20:假设一共有M个车库,编号1~M,时间点从早到晚是从1~T, 一共有N个记录,每一条记录如下{a, b, c
2021-08-25:给定数组father大小为N,表示一共有N个节点
2021-08-25:给定数组father大小为N,表示一共有N个节点,fatheri = j 表示点i的父亲是点j, father表示的树一定是一棵树而不是森林,queries是二维数组,大小为M*2,每一个长度为2的数组都表示一条查询,4,9, 表示想查询4和9之间的最低公共祖先…,3,7, 表示想查询3和7之间的最低公共祖先…,tree和queries里面的所有值,都一定在0~N-1之间。返回一个数组ans,大小为M,ansi表示第i条查询的答案。
福大大架构师每日一题
2021/08/25
3280
2021-08-25:给定数组father大小为N,表示一共有N个节点
2021-05-06:给定一个二维数组matrix, 你可以从任何位置
2021-05-06:给定一个二维数组matrix, 你可以从任何位置出发,走向上下左右四个方向 。返回能走出来的最长的递增链长度。
福大大架构师每日一题
2021/05/06
5800
2021-05-06:给定一个二维数组matrix, 你可以从任何位置
2021-02-25:给定一个正数数组arr,请把arr中所有的数分成两个集合。
2021-02-25:给定一个正数数组arr,请把arr中所有的数分成两个集合。如果arr长度为偶数,两个集合包含数的个数要一样多;如果arr长度为奇数,两个集合包含数的个数必须只差一个。请尽量让两个集合的累加和接近,返回最接近的情况下,较小集合的累加和。
福大大架构师每日一题
2021/02/25
3210
2021-02-25:给定一个正数数组arr,请把arr中所有的数分成两个集合。
推荐阅读
2021-12-28:给定一个二维数组matrix,matrix[i][j] = k代
2850
2023-05-07:给你一个大小为 n x n 二进制矩阵 grid 。最多 只能将一格 0 变成 1 。 返回执行此操作后,grid 中最大的岛屿面积是多少
4190
2021-07-17:一个不含有负数的数组可以代表一圈环形山,每
2060
2021-08-07:与数组中元素的最大异或值。给你一个由非负
3050
2021-08-16:回文对。给定一组 互不相同 的单词, 找出所
2470
2021-04-27:如果一个字符相邻的位置没有相同字符
4930
2021-04-30:一条直线上有居民点,邮局只能建在居民点上。给定一个有序正数数组arr
5030
2021-05-20:给定一个数组arr, 返回如果排序之后,相邻两数
3650
​2021-05-14:给定一个数组arr,想知道arr中哪两个数的异或结果最大。
5670
2021-09-05:单词搜索 II。给定一个 m x n 二维字符网格 bo
2860
2025-01-27:包含所有 1 的最小矩形面积Ⅱ。用go语言,给定一个二维二进制数组,找到三个非重叠且面积非零的矩形,这三个
830
2021-04-03:给定两个字符串str1和str2,想把str2整体插入到str1中的某个
5720
2021-06-26:给定一个只有0和1组成的二维数组,返回边框全是1的最大正方形面积。
4420
2021-07-30:两个有序数组间相加和的Topk问题。给定两个
3550
2021-10-26:给定一个数组arr,arr[i] = j,表示第i号试题的
3320
2021-04-18:给定一个二维数组matrix,里面的值不是1就是0,
4230
2023-07-20:假设一共有M个车库,编号1~M,时间点从早到晚是从1~T, 一共有N个记录,每一条记录如下{a, b, c
2930
2021-08-25:给定数组father大小为N,表示一共有N个节点
3280
2021-05-06:给定一个二维数组matrix, 你可以从任何位置
5800
2021-02-25:给定一个正数数组arr,请把arr中所有的数分成两个集合。
3210
相关推荐
2021-12-28:给定一个二维数组matrix,matrix[i][j] = k代
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档