934. 最短的桥

简介: 934. 最短的桥

@TOC


前言

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

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

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

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/shortest-bridge
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路

在这里插入图片描述
从第一片1广播
在这里插入图片描述
第二片1广播
两者广播相同位置的相加数中的最小值-3即为最短的桥
为什么要-3呢
因为有重复的部分,
第一片1到自己的距离为1,
第二片1到自己的距离也是1,
第一片1和第二片1到2这个点的距离为2-1,重复了一个1
在这里插入图片描述

二维变一维的技巧.
二维坐标对应的是一维坐标中的i*列数+j
一维坐标怎么判断有没有上下左右
在这里插入图片描述
1)a%列数=0,也就是最左边
2)a%列数=列数-1,也就是在最后一列,没有右边
3)a/行数=0,在第一行
4)a/行=行-1,在最后一行

在这里插入图片描述

在这里插入图片描述
第一片的队列curs跟record
cur记录的1的一维坐标
next代表感染的一维坐标
在这里插入图片描述

在第二个1中
可以往下扩展
因此next填入8,也就是正方形的位置
在这里插入图片描述

当队列遍历完后,next变成curs
进行下一轮的扩展

代码

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

    // 当前来到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
    public static int infect(int[][] m, int i, int j, int N, int M, int[] curs, int index, int[] record) {
        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;
        int p = i * M + j;
        record[p] = 1;
        // 收集到不同的1
        curs[index++] = p;
        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里面拿距离
    public static int bfs(int N, int M, int all, int V, 
            int[] curs, int size, int[] nexts, int[] record) {
        int nexti = 0; // 我要生成的下一层队列成长到哪了?
        for (int i = 0; i < size; i++) {
            // curs[i] -> 一个位置
            int up = curs[i] < M ? -1 : curs[i] - M;
            int down = curs[i] + M >= all ? -1 : curs[i] + M;
            int left = curs[i] % M == 0 ? -1 : curs[i] - 1;
            int right = curs[i] % M == M - 1 ? -1 : curs[i] + 1;
            if (up != -1 && record[up] == 0) {
                record[up] = V;
                nexts[nexti++] = up;
            }
            if (down != -1 && record[down] == 0) {
                record[down] = V;
                nexts[nexti++] = down;
            }
            if (left != -1 && record[left] == 0) {
                record[left] = V;
                nexts[nexti++] = left;
            }
            if (right != -1 && record[right] == 0) {
                record[right] = V;
                nexts[nexti++] = right;
            }
        }
        return nexti;
    }
相关文章
|
8月前
|
算法 测试技术 图计算
|
1月前
|
网络协议 网络架构
MAC地址震荡,STP震荡,OSPF路由协议震荡
MAC地址震荡,STP震荡,OSPF路由协议震荡
30 0
|
10月前
|
算法 C++
探索最小生成树:连通世界的最短纽带
生活中,我们常常需要在一组地点之间建立联系,这些联系可能是道路、管道、电缆等。然而,资源有限,成本宝贵。在这种情况下,如何以最小的代价将这些地点连接起来,成为了一个关键问题。这就引出了图论中的一个重要概念:最小生成树(Minimum Spanning Tree,MST)。本文将通过一个日常生活的案例,详细探讨最小生成树的概念、应用。
56 0
|
1月前
leetcode-934:最短的桥
leetcode-934:最短的桥
26 0
|
11月前
|
机器学习/深度学习
1350:【例4-11】最短网络(agrinet)
1350:【例4-11】最短网络(agrinet)
|
11月前
桥 接模式
桥 接模式
42 0
|
存储 计算机视觉
【每日一题Day7】LC934.最短的桥
给你一个大小为 n x n 的二元矩阵 grid ,其中 1 表示陆地,0 表示水域。岛 是由四面相连的 1 形成的一个最大组,即不会与非组内的任何其他 1 相连。grid 中 恰好存在两座岛 。
67 0
|
调度
L2-014 列车调度 (25 分)(二分)
L2-014 列车调度 (25 分)(二分)
155 0
L2-014 列车调度 (25 分)(二分)
LeetCode每日一题——934. 最短的桥
给你一个大小为 n x n 的二元矩阵 grid ,其中 1 表示陆地,0 表示水域。
85 0
7-169 汉密尔顿回路 (25 分)
7-169 汉密尔顿回路 (25 分)
117 0