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;
    }
相关文章
|
IDE 开发工具
【DIY无人机】电调固件升级
如何升级固件,提升电调性能?
1182 1
【DIY无人机】电调固件升级
|
12月前
|
缓存 Java 网络架构
vue2进阶篇:vue-router之“使用组件内路由守卫”
vue2进阶篇:vue-router之“使用组件内路由守卫”
143 1
|
12月前
|
人工智能 机器人 芯片
【通义】AI视界|苹果发布macOS Sequoia 15.1最新公测版:可体验Apple Intelligence
本文概览了近期科技动态,包括英伟达与台积电合作遇阻、亿万富翁投资者Druckenmiller后悔清仓英伟达、阿斯麦财报显示芯片需求复苏缓慢、苹果发布macOS Sequoia 15.1公测版及波士顿动力与丰田合作推进人形机器人技术。更多信息,请访问通义。
|
12月前
|
存储 安全 大数据
CDGA|数据流通新策略:高效利用,解锁数字经济新动能
在数字化时代,数据成为推动经济社会发展的关键要素。然而,数据孤岛、安全隐私及标准化不足等问题制约了其高效利用。本文探讨数据流通的新策略,包括强化数据治理、技术创新、安全保护及标准化建设,旨在构建高效利用体系,赋能数字经济高质量发展,激发数据要素潜能,推动产业升级与经济转型。
|
11月前
|
安全 测试技术 API
如何实现API接口的自动化测试?
实现API接口的自动化测试涉及多个关键步骤:确定测试范围和目标、编写测试用例、选择自动化测试工具、搭建测试环境、编写测试脚本、执行测试、分析结果和回归测试。选择合适的工具和考虑团队熟悉度是成功的关键。常用工具包括Postman、JMeter和SoapUI。通过这些步骤和工具,可以有效提高测试效率和质量,确保API的稳定性和可靠性。
|
缓存 运维 前端开发
大淘宝技术行业FaaS化实战经验分享
本文将分享我们在FaaS化过程中的经验,尝试回答关于FaaS的Why、What、How三个问题,给对FaaS有兴趣的同学提供一些实践经验。
1421 0
大淘宝技术行业FaaS化实战经验分享
|
数据库
代码自动生成工具实战-Cursor
之前看过github copilot 的代码生成能力。可以说解放了码农的双手,基础的代码完全可以来生成。可是后来它收费了。
672 0
|
人工智能 运维 监控
独家 | 蚂蚁金服TRaaS技术风险防控平台解密
蚂蚁金服技术风险防控平台TRaaS的前世今生。
5993 0
|
XML JSON 缓存
Java实现天眼查API根据企业纳税识别号查询企业详情数据方法
Java实现天眼查API根据企业纳税识别号查询企业详情数据方法