华为OD机试 - 返回矩阵中非1的元素个数 - 广度优先搜索BFS(Python/JS/C/C++ 2024 E卷 200分)

news2024/9/19 8:49:39

在这里插入图片描述

华为OD机试 2024E卷题库疯狂收录中,刷题点这里

专栏导读

本专栏收录于《华为OD机试真题(Python/JS/C/C++)》。

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。

一、题目描述

存在一个m*n的二维数组Q,其成员取值范围为0,1,2。

其中值为1的元素具备向四周传染的特性,每经过1s,将上下左右值为0的元素同化为1。

而值为2的元素,免疫同化。

将数组所有成员随机初始化为0或2,再将矩阵的[0, 0]元素修改成1,在经过足够长的时间后求矩阵中有多少个元素是0或2(即0和2数量之和)。

二、输入描述

输入人的前两个数字是矩阵大小。后面是数字矩阵内容。

三、输出描述

返回矩阵中非1的元素个数。

四、测试用例

测试用例1:

1、输入

4 4
0 0 0 0
0 2 2 2
0 2 0 0
0 2 0 0

2、输出

9

3、说明

起始位置 (0, 0) 被修改为 1 后,开始进行感染传播。

感染从 (0, 0) 向四周扩散,传播到与其相邻的上下左右位置:

  • 第一行的所有元素 (0, 1)、(0, 2)、(0, 3) 被感染,修改为 1。
  • 第二行的 (1, 0) 被感染,修改为 1。
  • 第三行的 (2, 0) 被感染,修改为 1。
  • 第四行的 (3, 0) 被感染,修改为 1。

感染传播会遇到值为 2 的元素,这些元素免疫感染,因此在接触到值为 2 的位置时停止扩散。

最终矩阵状态:

1 1 1 1
1 2 2 2
1 2 0 0
1 2 0 0

最终矩阵中,所有的 0 和 2 均未被感染。共计有 9 个非 1 元素(包括 7 个 2 和 2 个 0)。

非 1 元素的总数量为 9,所以输出 9。

测试用例2:

1、输入

3 3
0 0 0
0 2 0
0 0 0

2、输出

1

3、说明

初始矩阵大小为 3x3,(0,0) 元素被修改为 1,传播后矩阵为:

1 1 1
1 2 1
1 1 1

矩阵中只有一个非 1 元素(2),所以输出 1。

五、解题思路

1、为什么采用广度优先搜索BFS?

BFS 在逐层扩展问题中性能优异。在此问题中,感染逐步向周围扩散,与 BFS 的性质吻合。BFS 通过队列的先进先出特性,确保每一层的感染是按序处理的,避免漏掉任何可以传播的方向。

使用队列(FIFO)数据结构来存储每次感染扩散的节点。每次取出队列的节点,扩散到其周围的上下左右位置,将符合条件的新位置加入队列,表示它们将被下一轮感染。

2、具体步骤:

  1. 初始化矩阵:
    • 首先,读取输入的矩阵大小 m 和 n,然后读取矩阵的元素内容。
    • 将矩阵的 [0,0] 元素设置为 1,表示起始感染的位置。
  2. 传播感染:
    • 广度优先搜索(BFS):使用队列来模拟感染的传播过程。首先,将初始感染位置 [0,0] 加入队列,然后每次从队列中取出一个位置,检 查其上下左右四个方向。如果该方向的元素为 0,将其修改为 1,表示感染扩散,并将该位置加入队列。
    • 采用 BFS 是因为感染是逐步向四周扩散的,这种逐层扩散的过程符合 BFS 的特性。
  3. 边界检查:
    • 在扩散过程中,检查每个新位置是否在矩阵边界内,以避免越界错误。
    • 还要检查目标位置是否为 0,因为只有值为 0 的位置可以被感染。
  4. 统计非 1 元素的个数:
    • 感染扩散完成后,遍历整个矩阵,统计值为 0 和 2 的元素数量,这两个元素代表未被感染的区域和免疫区域。
  5. 输出结果:
    • 最后,输出矩阵中非 1 元素的数量。

3、时间复杂度

O(m * n),其中 m 和 n 是矩阵的行数和列数。最坏情况下,所有的元素都需要被遍历和检查一次。

4、空间复杂度

O(m * n),主要是队列中可能会存储矩阵中所有的元素位置,尤其是当所有元素都需要被感染或被检查时。

六、Python算法源码

使用 collections.deque 模拟队列进行 BFS 操作,读取输入矩阵大小和内容,并进行感染传播。

from collections import deque

# 定义四个方向数组,分别代表上下左右的移动
dx = [-1, 1, 0, 0]
dy = [0, 0, -1, 1]

def main():
    # 输入矩阵大小
    m, n = map(int, input().split())
    matrix = []

    # 输入矩阵内容
    for _ in range(m):
        matrix.append(list(map(int, input().split())))

    # 将 [0, 0] 位置修改为 1
    matrix[0][0] = 1

    # 使用队列进行广度优先搜索(BFS)以传播感染
    queue = deque()
    queue.append((0, 0))  # 初始位置加入队列

    while queue:
        x, y = queue.popleft()

        # 遍历四个方向
        for i in range(4):
            newX = x + dx[i]
            newY = y + dy[i]

            # 检查边界和感染条件
            if 0 <= newX < m and 0 <= newY < n and matrix[newX][newY] == 0:
                matrix[newX][newY] = 1  # 将值修改为 1,表示感染
                queue.append((newX, newY))  # 将新位置加入队列

    # 统计非1的元素个数(即0和2的个数)
    count = sum(matrix[i][j] in [0, 2] for i in range(m) for j in range(n))

    # 输出结果
    print(count)

if __name__ == "__main__":
    main()

七、JavaScript算法源码

使用数组作为队列,shift 方法用于出队,模拟 BFS 感染过程,读取输入并输出结果。

function main() {
    // 定义四个方向数组,分别代表上下左右的移动
    const dx = [-1, 1, 0, 0];
    const dy = [0, 0, -1, 1];

    // 输入矩阵大小
    const input = prompt("Enter matrix size and elements:").split("\n");
    const [m, n] = input[0].split(' ').map(Number);
    let matrix = [];

    // 输入矩阵内容
    for (let i = 0; i < m; i++) {
        matrix.push(input[i + 1].split(' ').map(Number));
    }

    // 将 [0, 0] 位置修改为 1
    matrix[0][0] = 1;

    // 使用队列进行广度优先搜索(BFS)以传播感染
    let queue = [];
    queue.push([0, 0]); // 初始位置加入队列

    while (queue.length > 0) {
        let [x, y] = queue.shift();

        // 遍历四个方向
        for (let i = 0; i < 4; i++) {
            let newX = x + dx[i];
            let newY = y + dy[i];

            // 检查边界和感染条件
            if (newX >= 0 && newX < m && newY >= 0 && newY < n && matrix[newX][newY] === 0) {
                matrix[newX][newY] = 1; // 将值修改为 1,表示感染
                queue.push([newX, newY]); // 将新位置加入队列
            }
        }
    }

    // 统计非1的元素个数(即0和2的个数)
    let count = 0;
    for (let i = 0; i < m; i++) {
        for (let j = 0; j < n; j++) {
            if (matrix[i][j] === 0 || matrix[i][j] === 2) {
                count++;
            }
        }
    }

    // 输出结果
    console.log(count);
}

main();

八、C算法源码

使用数组模拟队列进行 BFS,由于 C 语言没有内置队列,手动实现一个队列结构,包含元素添加和移除的逻辑。

#include <stdio.h>

#define MAX 100

// 定义四个方向数组,分别代表上下左右的移动
int dx[] = {-1, 1, 0, 0};
int dy[] = {0, 0, -1, 1};

typedef struct {
    int x, y;
} Point;

int main() {
    int m, n;
    int matrix[MAX][MAX];
    Point queue[MAX * MAX];
    int front = 0, rear = 0;

    // 输入矩阵大小
    scanf("%d %d", &m, &n);

    // 输入矩阵内容
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            scanf("%d", &matrix[i][j]);
        }
    }

    // 将 [0, 0] 位置修改为 1
    matrix[0][0] = 1;

    // 使用队列进行广度优先搜索(BFS)以传播感染
    queue[rear++] = (Point){0, 0}; // 初始位置加入队列

    while (front < rear) {
        Point current = queue[front++];
        int x = current.x;
        int y = current.y;

        // 遍历四个方向
        for (int i = 0; i < 4; i++) {
            int newX = x + dx[i];
            int newY = y + dy[i];

            // 检查边界和感染条件
            if (newX >= 0 && newX < m && newY >= 0 && newY < n && matrix[newX][newY] == 0) {
                matrix[newX][newY] = 1; // 将值修改为 1,表示感染
                queue[rear++] = (Point){newX, newY}; // 将新位置加入队列
            }
        }
    }

    // 统计非1的元素个数(即0和2的个数)
    int count = 0;
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            if (matrix[i][j] == 0 || matrix[i][j] == 2) {
                count++;
            }
        }
    }

    // 输出结果
    printf("%d\n", count);

    return 0;
}

九、C++算法源码

使用 STL 中的 queue 数据结构进行 BFS 操作,pair 用于存储坐标,并模拟感染传播。

#include <iostream>
#include <queue>

using namespace std;

// 定义四个方向数组,分别代表上下左右的移动
int dx[] = {-1, 1, 0, 0};
int dy[] = {0, 0, -1, 1};

int main() {
    int m, n;
    cin >> m >> n;
    int matrix[m][n];

    // 输入矩阵内容
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            cin >> matrix[i][j];
        }
    }

    // 将 [0, 0] 位置修改为 1
    matrix[0][0] = 1;

    // 使用队列进行广度优先搜索(BFS)以传播感染
    queue<pair<int, int>> q;
    q.push({0, 0}); // 初始位置加入队列

    while (!q.empty()) {
        pair<int, int> current = q.front();
        q.pop();
        int x = current.first;
        int y = current.second;

        // 遍历四个方向
        for (int i = 0; i < 4; i++) {
            int newX = x + dx[i];
            int newY = y + dy[i];

            // 检查边界和感染条件
            if (newX >= 0 && newX < m && newY >= 0 && newY < n && matrix[newX][newY] == 0) {
                matrix[newX][newY] = 1; // 将值修改为 1,表示感染
                q.push({newX, newY}); // 将新位置加入队列
            }
        }
    }

    // 统计非1的元素个数(即0和2的个数)
    int count = 0;
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            if (matrix[i][j] == 0 || matrix[i][j] == 2) {
                count++;
            }
        }
    }

    // 输出结果
    cout << count << endl;

    return 0;
}


🏆下一篇:华为OD机试真题 - 简易内存池(Python/JS/C/C++ 2024 E卷 200分)

🏆本文收录于,华为OD机试真题(Python/JS/C/C++)

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2145923.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

最长连续子序列 - 华为OD统一考试(E卷)

OD统一考试&#xff08;E卷&#xff09; 分值&#xff1a; 100分 题解&#xff1a; Java / Python / C 2024华为OD机试&#xff08;E卷D卷C卷&#xff09;最新题库【超值优惠】Java/Python/C合集 题目描述 有N个正整数组成的一个序列。给定整数sum&#xff0c;求长度最长的连续…

WIFI路由器的套杆天线简谈

❝本次推文简单介绍下WIFI路由器的套杆天线。 路由器天线 路由器在这个万物互联的时代&#xff0c;想必大家对其都不陌生。随着科技的发展&#xff0c;常用的路由器上的天线也越来越多&#xff0c;那么问题来了&#xff1a;天线越多&#xff0c;信号越好吗&#xff1f;路由器…

前端mock了所有……

目录 一、背景描述 二、开发流程 1.引入Mock 2.创建文件 3.需求描述 4.Mock实现 三、总结 一、背景描述 前提&#xff1a; 事情是这样的&#xff0c;老板想要我们写一个demo拿去路演/拉项目&#xff0c;有一些数据&#xff0c;希望前端接一下&#xff0c;写几个表格&a…

Linux进程间通信——探索共享内存—— 剖析原理, 学习接口应用

前言&#xff1a;本节内容主要讲解进程间通信的&#xff0c; systemV版本下的共享内存。 共享内存&#xff0c;顾名思义&#xff0c; 其实就是一块内存&#xff0c; 它不同于管道是一个文件。 所以它的传输速度是很快的。 因为管道是文件&#xff0c;有缓冲区&#xff0c; 而共…

Day99 代码随想录打卡|动态规划篇--- 01背包问题

题目&#xff08;卡玛网T46&#xff09;&#xff1a; 小明是一位科学家&#xff0c;他需要参加一场重要的国际科学大会&#xff0c;以展示自己的最新研究成果。他需要带一些研究材料&#xff0c;但是他的行李箱空间有限。这些研究材料包括实验设备、文献资料和实验样本等等&am…

LeRobot - 让现实机器人更易学

文章目录 一、关于 LeRobot特点模拟环境中预训练模型的示例 致谢教程 - Getting Started with Real-World Robots 二、安装三、Walkthrough1、可视化数据集2、LeRobotDataset的格式3、评估预先训练的策略4、训练你自己的政策复制最先进的&#xff08;SOTA&#xff09; 四、贡献…

Vue3 中 Aos 动画同时触发的解决办法

文章目录 问题现象解决之后的效果解决办法问题猜测 问题现象 我总共有四行数据&#xff0c;每一行都是一个动画&#xff0c;但是触发第一个之后其他三个也都触发了 我想要的效果是&#xff1a;动画从底部出现的时候触发一个动画&#xff0c;不要都触发掉 解决之后的效果 解决…

智慧卫生间系统:引领公共卫生间管理的新时代@卓振思众

随着城市化进程的加快&#xff0c;公共卫生间的使用频率不断增加。如何提升公共卫生间的使用体验、管理效率以及卫生水平&#xff0c;已成为各地政府和管理者关注的焦点。智慧卫生间系统应运而生&#xff0c;成为解决这一问题的重要工具。它结合了物联网技术和智能管理理念&…

四、Cookie 和 Session

文章目录 1. Cookie 饼干1.1 什么是 Cookie?1.2 如何创建 Cookie1.3 服务器如何获取 Cookie1.4 Cookie 值的修改1.5 浏览器查看 Cookie1.6 Cookie 生命控制&#xff08;指浏览器中Cookie的存在时间&#xff09;1.7 Cookie 有效路径 Path 的设置 2. Session 会话2.1 什么是 Ses…

Canopen-pn有线通信标准在汽车制造中至关重要

电子元件越来越多地被集成到车辆中&#xff0c;从而实现与物联网世界的连接。该行业中主要的高速串行接口方法包括控制器局域网 (CAN) 总线 。CAN 是运输应用中使用的一种强大的总线标准。它旨在允许微控制器(MCU) 和相关组件与彼此的应用程序进行通信。这无需系统具有主机即可…

从入门到精通,带你探索适合新手的视频剪辑工具

用视频来分享生活已经变成越来越多人的一种习惯&#xff0c;很多时候视频并不能一镜到底&#xff0c;所以还需要一些的修改、剪辑操作&#xff0c;那么这次我将介绍几款视频剪辑工具&#xff0c;希望能够让你分享的道路更加通畅。 1.FOXIT视频剪辑 连接直达>>https://w…

【项目设计】Facial-Hunter

目录 一、项目介绍 二、开发环境以及技术 三、项目架构设计 3.1 项目总体架构 3.2 客户端架构 3.3 主服务端架构 3.4 处理服务端架构 3.5 数据库设计 四、FaceNet 五、代码实现 一、项目介绍 该项目是基于深度学习与负载均衡的人脸识别系统 该项目主要由三个部分组…

【Elasticsearch系列十二】聚合-电视案例

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

反射的相关内容

目录 一、什么是反射 二、为什么会有反射 三、反射是如何工作的 获取类信息的三种方式&#xff1a; 例&#xff1a; 四、获取类信息并调用 1.获取 &#xff08;1&#xff09;获取变量 获取全部类信息 获取public修饰的 获取指定某一个 &#xff08;2&#xff09;…

【新手上路】衡石分析平台使用手册-租户管理

租户管理​ 衡石系统支持服务一个平台方和多个企业客户的租户模式&#xff0c;平台方管理租户&#xff0c;为租户提供数据&#xff0c;租户在系统内进行数据分析。 衡石系统增加工作空间的设计&#xff0c;在平台方和租户之间提供单向的传递通道&#xff0c;平台厂商可以轻松…

C++map,set,multiset,multimap详细介绍

目录 1. 关联式容器 2. 键值对 3. 树形结构的关联式容器 3.1 set set的介绍 set的使用 1. set的模板参数列表 2. set的构造 3. set的迭代器 4. set的容量 5. set的修改操作 6. set的使用举例 ​3.2 map map的介绍 map的使用 1. map的模板参数声明 2. map的构造 …

实例讲解电动汽车钥匙ON挡上下电控制策略及Simulink建模方法

在电动汽车VCU开发中&#xff0c;上下电控制是其中一个核心控制内容&#xff0c;也是其他控制功能的基础&#xff0c;而钥匙ON挡上下电又是整车上下电的基础。本文介绍电动汽车钥匙ON挡上下电的控制策略及Simulink建模方法。 目录 一、整车高压原理 二、钥匙ON挡上下电控制策…

计算机毕业设计 办公用品管理系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

Aegisub字幕自动化及函数篇(图文教程附有gif动图展示)(一)

目录 自动化介绍 bord 边框宽度 随机函数 fsvp 随机颜色 move 自动化介绍 自动化介绍:简单来说自动化能让所有字幕行快速拥有你指定的同一种特效 对时间不同的行应用相同的效果 只要设计好一个模板&#xff0c;然后让所有行都执行这个模板上的特效就好了 首先制作模板行…

kafka消息发送几种方式

同步发送 or 异步发送 消息发送根据是否需要处理发送的结果分为同步发送、异步发送。 同步发送&#xff1a;等待发送结果返回&#xff0c;这种方式是可靠的&#xff0c;因为异常能及时处理&#xff0c;但同步发送需要阻塞等待一条消息发送完才处理下一条&#xff0c;吞吐量差。…