华为OD机试 2024E卷题库疯狂收录中,刷题点这里
专栏导读
本专栏收录于《华为OD机试真题(Python/JS/C/C++)》。
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。
一、题目描述
服务器连接方式包括直接相连,间接连接。A 和 B 直接连接,B 和 C 直接连接,则 A 和 C 间接连接。直接连接和间接连接都可以发送广播。
给出一个 N * N 数组,代表 N 个服务器,matrix[i][j] == 1,则代表 i 和 j 直接连接;不等于 1 时,代表 i 和 j 不直接连接。
matrix[i][i] == 1,即自己和自己直接连接。matrix[i][j] == matrix[j][i]。
计算初始需要给几台服务器广播,才可以使每个服务器都收到广播。
二、输入描述
输入描述输入为 N 行,每行有 N 个数字,为 0 或 1,由空格分隔,构成 N * N 的数组,N 的范围为 1 <= N <= 50。
三、输出描述
输出一个数字,为需要广播的服务器数量。
四、测试用例
测试用例1
1、输入
1 0 0
0 1 0
0 0 1
2、输出
3
3、说明
3 台服务器相互不连接,所以需要分别广播这 3 台服务器。
测试用例2
1、输入
1 0 1 0 0 0 1
0 1 0 0 1 1 0
1 0 1 0 0 0 0
0 0 0 1 0 0 0
0 1 0 0 1 0 0
0 1 0 0 0 1 0
1 0 0 0 0 0 1
2、输出
3
五、解题思路
并查集是一种非常有效的数据结构,用于处理不交集的合并及查询问题。在本题中,我们可以利用并查集来追踪服务器之间的连接关系,从而确定最少需要广播的服务器数量,即图中的连通分量数量。
解题思路:
- 初始化并查集:每个服务器最开始都是自己的代表,因此初始时有 N 个连通分量。
- 合并操作:对于矩阵中每一个值为 1 的点,如果两个服务器尚未连接,则通过并查集将它们合并。
- 压缩路径:并查集的查找操作中,利用路径压缩技术优化查找效率。
- 计算连通分量:遍历所有服务器,通过并查集找出不同的根节点,每个独立的根节点代表一个连通分量。
- 输出结果:输出连通分量的数量,即最少需要广播的服务器数量。
六、Python算法源码
class OdTest03:
def __init__(self):
self.parent = [] # 存储每个元素的父节点
self.rank = [] # 用于按秩合并优化
def find(self, x):
# 并查集查找操作,带路径压缩
if self.parent[x] != x:
self.parent[x] = self.find(self.parent[x]) # 路径压缩
return self.parent[x]
def union(self, x, y):
# 并查集合并操作,按秩合并
rootX = self.find(x)
rootY = self.find(y)
if rootX != rootY:
if self.rank[rootX] > self.rank[rootY]:
self.parent[rootY] = rootX
elif self.rank[rootX] < self.rank[rootY]:
self.parent[rootX] = rootY
else:
self.parent[rootY] = rootX
self.rank[rootX] += 1
def main(self):
arr = list(map(int, input().split())) # 读取一行输入,并将其转换为整数数组
N = len(arr) # 服务器数量 N
matrix = [arr] # 创建矩阵并初始化第一行
for i in range(1, N):
matrix.append(list(map(int, input().split()))) # 读取输入的矩阵数据
# 初始化并查集
self.parent = [i for i in range(N)]
self.rank = [0] * N
# 并查集合并操作
for i in range(N):
for j in range(i + 1, N):
if matrix[i][j] == 1:
self.union(i, j)
# 计算连通分量的数量
count = len(set(self.find(i) for i in range(N))) # 使用集合来计算不同的根节点数量
print(count) # 输出需要广播的服务器数量
# 执行代码
if __name__ == "__main__":
test = OdTest03()
test.main()
七、JavaScript算法源码
class OdTest03 {
constructor() {
this.parent = []; // 存储每个元素的父节点
this.rank = []; // 用于按秩合并优化
}
find(x) {
// 并查集查找操作,带路径压缩
if (this.parent[x] !== x) {
this.parent[x] = this.find(this.parent[x]); // 路径压缩
}
return this.parent[x];
}
union(x, y) {
// 并查集合并操作,按秩合并
let rootX = this.find(x);
let rootY = this.find(y);
if (rootX !== rootY) {
if (this.rank[rootX] > this.rank[rootY]) {
this.parent[rootY] = rootX;
} else if (this.rank[rootX] < this.rank[rootY]) {
this.parent[rootX] = rootY;
} else {
this.parent[rootY] = rootX;
this.rank[rootX]++;
}
}
}
main() {
const arr = prompt().split(" ").map(Number); // 读取输入,并转换为整数数组
const N = arr.length; // 服务器数量 N
const matrix = [arr]; // 创建矩阵并初始化第一行
for (let i = 1; i < N; i++) {
matrix.push(prompt().split(" ").map(Number)); // 读取输入的矩阵数据
}
// 初始化并查集
this.parent = Array.from({ length: N }, (_, i) => i);
this.rank = Array(N).fill(0);
// 并查集合并操作
for (let i = 0; i < N; i++) {
for (let j = i + 1; j < N; j++) {
if (matrix[i][j] === 1) {
this.union(i, j);
}
}
}
// 计算连通分量的数量
let count = new Set(this.parent.map((_, i) => this.find(i))).size; // 使用 Set 计算不同的根节点数量
console.log(count); // 输出需要广播的服务器数量
}
}
// 执行代码
let test = new OdTest03();
test.main();
八、C算法源码
#include <stdio.h>
#define MAX 100
int parent[MAX]; // 存储每个元素的父节点
int rank[MAX]; // 用于按秩合并优化
int find(int x) {
// 并查集查找操作,带路径压缩
if (parent[x] != x) {
parent[x] = find(parent[x]); // 路径压缩
}
return parent[x];
}
void union_sets(int x, int y) {
// 并查集合并操作,按秩合并
int rootX = find(x);
int rootY = find(y);
if (rootX != rootY) {
if (rank[rootX] > rank[rootY]) {
parent[rootY] = rootX;
} else if (rank[rootX] < rank[rootY]) {
parent[rootX] = rootY;
} else {
parent[rootY] = rootX;
rank[rootX]++;
}
}
}
int main() {
int N;
scanf("%d", &N); // 读取服务器数量
int matrix[MAX][MAX];
// 读取输入的矩阵数据
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
scanf("%d", &matrix[i][j]);
}
}
// 初始化并查集
for (int i = 0; i < N; i++) {
parent[i] = i;
rank[i] = 0;
}
// 并查集合并操作
for (int i = 0; i < N; i++) {
for (int j = i + 1; j < N; j++) {
if (matrix[i][j] == 1) {
union_sets(i, j);
}
}
}
// 计算连通分量的数量
int count = 0;
for (int i = 0; i < N; i++) {
if (find(i) == i) {
count++;
}
}
printf("%d\n", count); // 输出需要广播的服务器数量
return 0;
}
九、C++算法源码
#include <iostream>
#include <vector>
#include <set>
using namespace std;
class OdTest03 {
private:
vector<int> parent; // 存储每个元素的父节点
vector<int> rank; // 用于按秩合并优化
public:
OdTest03(int N) {
parent.resize(N);
rank.resize(N, 0);
for (int i = 0; i < N; i++) {
parent[i] = i;
}
}
int find(int x) {
// 并查集查找操作,带路径压缩
if (parent[x] != x) {
parent[x] = find(parent[x]); // 路径压缩
}
return parent[x];
}
void union_sets(int x, int y) {
// 并查集合并操作,按秩合并
int rootX = find(x);
int rootY = find(y);
if (rootX != rootY) {
if (rank[rootX] > rank[rootY]) {
parent[rootY] = rootX;
} else if (rank[rootX] < rank[rootY]) {
parent[rootX] = rootY;
} else {
parent[rootY] = rootX;
rank[rootX]++;
}
}
}
void process_matrix(int N, vector<vector<int>>& matrix) {
// 并查集合并操作
for (int i = 0; i < N; i++) {
for (int j = i + 1; j < N; j++) {
if (matrix[i][j] == 1) {
union_sets(i, j);
}
}
}
// 计算连通分量的数量
set<int> roots;
for (int i = 0; i < N; i++) {
roots.insert(find(i)); // 使用 set 来存储不同的根节点
}
cout << roots.size() << endl; // 输出需要广播的服务器数量
}
};
int main() {
int N;
cin >> N; // 读取服务器数量
vector<vector<int>> matrix(N, vector<int>(N));
// 读取输入的矩阵数据
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
cin >> matrix[i][j];
}
}
OdTest03 test(N);
test.process_matrix(N, matrix); // 处理矩阵并计算结果
return 0;
}
🏆下一篇:华为OD机试真题 - 简易内存池(Python/JS/C/C++ 2024 E卷 200分)
🏆本文收录于,华为OD机试真题(Python/JS/C/C++)
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。