【笔试题汇总】华为春招笔试题解 2024-4-10

2024.04.10-春招第二场

01.LYA 的云服务计费系统

问题描述

LYA 是一家云服务提供商,她需要为客户提供云服务计费功能。现在,她有一份包含多条计费日志的文件,每条日志包含时间戳、客户标识、计费因子和计费时长四个字段。此外,她还有一份计费因子的单价列表。

LYA 需要编写一个程序,根据计费日志和计费因子单价列表,计算每个客户的话单总费用。需要注意的是,如果同一客户在相同时间戳上报了多条相同计费因子的日志,只能计费一次,并且选择先上报的日志进行计费。

输入格式

第一行包含一个正整数 n n n,表示计费日志的条数, 1 ≤ n ≤ 1000 1 \leq n \leq 1000 1n1000

接下来的 n n n 行,每行包含四个字段,分别表示时间戳(长度为 10 10 10 的数字字符串)、客户标识(长度为 1 ∼ 16 1 \sim 16 116 的字符串)、计费因子(长度为 1 ∼ 16 1 \sim 16 116 的字符串)和计费时长(范围为 0 ∼ 100 0 \sim 100 0100 的整数),字段之间用逗号分隔。如果计费因子在单价列表中查不到,则认为其单价为 0 0 0;如果计费时长不在 0 ∼ 100 0 \sim 100 0100 的范围内,则认为计费时长为 0 0 0

接下来一行包含一个正整数 m m m,表示计费因子的数量, 1 ≤ m ≤ 100 1 \leq m \leq 100 1m100

最后的 m m m 行,每行包含两个字段,分别表示计费因子(长度为 1 ∼ 16 1 \sim 16 116 的字符串)和单价(范围为 1 ∼ 100 1 \sim 100 1100 的整数),字段之间用逗号分隔。

输出格式

输出每个客户的话单总费用,每行包含两个字段,分别表示客户标识和话单费用,字段之间用逗号分隔。输出按照客户标识的字典序升序排列。

样例输入

5
1627845600,client1,factorA,10
1627845605,client2,factorB,15
1627845610,client1,factorA,5
1627845615,client1,factorB,8
1627845620,client2,factorB,20
2
factorA,5
factorB,7

样例输出

client1,131
client2,245

数据范围

  • 1 ≤ n ≤ 1000 1 \leq n \leq 1000 1n1000
  • 1 ≤ m ≤ 100 1 \leq m \leq 100 1m100
  • 时间戳是长度为 10 10 10 的数字字符串
  • 客户标识和计费因子是长度为 1 ∼ 16 1 \sim 16 116 的字符串
  • 计费时长的范围为 0 ∼ 100 0 \sim 100 0100
  • 计费因子的单价范围为 1 ∼ 100 1 \sim 100 1100

【题目解析】

本题可以用DFS求解。基本思路如下:

  1. 枚举断开的节点 x x x,将其从 e x p o s e d exposed exposed 中移除。
  2. 对于 e x p o s e d exposed exposed 中的每个节点 u u u,从 u u u 开始DFS搜索所有可达的节点,并记录数量。权限等级初始为 10 10 10
  3. 如果当前节点 u u u 可以访问节点 v v v(即 m a t r i x [ u ] [ v ] matrix[u][v] matrix[u][v] 不为 0 0 0 且不超过当前权限等级),则将 v v v 加入DFS,并将权限等级更新为 m a t r i x [ u ] [ v ] matrix[u][v] matrix[u][v]
  4. 选择最终被入侵节点数量最少的 x x x 作为答案。如有多个,取编号最小的。

cpp

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

int n;
const int N = 30;
int a[N][N];
bool st[N];

int dfs(int id, int ra) {
    int num = 0, sm = 0;
    for (int i = 0; i < n; i++) {
        if (id == i || !a[id][i]) continue;
        if (ra >= a[id][i]) {
            if (st[i]) continue;
            st[i] = true;
            num += dfs(i, a[id][i]);
            st[i] = false;
        }
    }
    return num + 1;
}

int main() {
    cin >> n;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            cin >> a[i][j];

    int x;
    int res = -1, ans = 0;
    while (cin >> x) {
        for (int i = 0; i < n; i++) {
            if (x == i) continue;
            st[x] = true;
            int t = dfs(x, 10);
            st[x] = false;
            if (t > ans) {
                ans = t;
                res = x;
            }
        }
    }
    cout << res;
    return 0;
}

02.LYA 的图片分类算法

问题描述

LYA 是一位图像处理工程师,她需要设计一个算法来对一批图片进行分类。首先,她对每张图片提取特征,并计算任意两张图片之间的相似度。然后,根据以下规则将图片归类:

  1. 如果两张图片的相似度大于 0 0 0,则认为它们是相似的;
  2. 如果图片 A A A B B B 相似, B B B C C C 相似,但 A A A C C C 不相似,则认为 A A A C C C 是间接相似的,可以将 A A A B B B C C C 归为一类,但不计算 A A A C C C 的相似度;
  3. 如果一张图片与所有其他图片都不相似,则它自成一类,相似度为 0 0 0

给定一个大小为 N × N N \times N N×N 的矩阵 M M M,其中 M [ i ] [ j ] M[i][j] M[i][j] 表示第 i i i 张图片和第 j j j 张图片的相似度,请按照从大到小的顺序返回每个相似类中所有图片的相似度之和。

输入格式

第一行包含一个正整数 N N N 1 ≤ N ≤ 900 1 \leq N \leq 900 1N900),表示矩阵 M M M 中图片的数量。

接下来的 N N N 行,每行包含 N N N 个用空格分隔的非负整数,表示矩阵 M M M。其中, 0 ≤ M [ i ] [ j ] ≤ 100 0 \leq M[i][j] \leq 100 0M[i][j]100,并且保证 M [ i ] [ j ] = M [ j ] [ i ] M[i][j] = M[j][i] M[i][j]=M[j][i]

注意:输入的矩阵元素之间的分隔符可能是一个或多个连续的空格。

输出格式

输出每个相似类的相似度之和,按照从大到小的顺序输出。每个数占一行,相邻两个数之间用一个空格分隔。

样例输入

5
0 0 50 0 0
0 0 0 25 0
50 0 0 0 15
0 25 0 0 0
0 0 15 0 0

样例输出

65 25

数据范围

  • 1 ≤ N ≤ 900 1 \leq N \leq 900 1N900
  • 0 ≤ M [ i ] [ j ] ≤ 100 0 \leq M[i][j] \leq 100 0M[i][j]100

【题目解析】

首先,提取每张图片的特征并计算图片间的相似度矩阵。然后按照给定的规则对图片进行分类,并计算每个相似类中所有图片的相似度之和。

为了解决这个问题,我们可以采用深度优先搜索,并查集等方法来处理相似类的合并,然后计算相似度之和。使用并查集将相似的图片进行合并。接着计算每个相似类中所有图片的相似度之和,并按照从大到小的顺序输出。

cpp

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

class UnionFind {
private:
    vector<int> parent;
    vector<int> rank;
    
public:
    UnionFind(int n) {
        parent.resize(n);
        rank.resize(n);
        for (int i = 0; i < n; ++i) {
            parent[i] = i;
            rank[i] = 0;
        }
    }
    
    int find(int x) {
        if (x != parent[x]) {
            parent[x] = find(parent[x]);
        }
        return parent[x];
    }
    
    void merge(int x, int y) {
        int rootX = find(x);
        int rootY = find(y);
        if (rootX != rootY) {
            if (rank[rootX] < rank[rootY]) {
                parent[rootX] = rootY;
            } else if (rank[rootX] > rank[rootY]) {
                parent[rootY] = rootX;
            } else {
                parent[rootY] = rootX;
                rank[rootX]++;
            }
        }
    }
};

int main() {
    int N;
    cin >> N;
    
    vector<vector<int>> M(N, vector<int>(N));
    for (int i = 0; i < N; ++i) {
        for (int j = 0; j < N; ++j) {
            cin >> M[i][j];
        }
    }
    
    UnionFind uf(N);
    
    for (int i = 0; i < N; ++i) {
        for (int j = i + 1; j < N; ++j) {
            if (M[i][j] > 0) {
                uf.merge(i, j);
            }
        }
    }
    
    vector<int> sum(N, 0);
    for (int i = 0; i < N; ++i) {
        sum[uf.find(i)] += accumulate(M[i].begin(), M[i].end(), 0);
    }
    
    sort(sum.rbegin(), sum.rend());
    
    for (int i = 0; i < N; ++i) {
        if (sum[i] > 0) {
            cout << sum[i] << endl;
        }
    }
    
    return 0;
}

03.网络入侵检测

问题描述

K小姐是一名网络安全工程师,她负责维护一个由 N N N 个节点组成的内部网络。这个网络的连通性可以用一个 N × N N\times N N×N 的矩阵 m a t r i x matrix matrix 来表示,其中 m a t r i x [ i ] [ j ] = p matrix[i][j]=p matrix[i][j]=p 表示从节点 i i i 到节点 j j j 需要的最低权限等级为 p p p p = 0 p=0 p=0 表示不连通)。如果成功访问了节点 j j j,则该节点的权限等级会被调整为 p p p

某天,K小姐发现有一些节点暴露在了公网上,存在被外部攻击的风险。暴露节点的编号保存在数组 e x p o s e d exposed exposed 中。如果攻击者从公网入侵了某个暴露节点,则该节点的权限等级会变为最高等级 10 10 10。同时,入侵可以在网络内部传播,只要满足权限等级的要求即可。

为了尽快控制损失,K小姐决定立即将某个暴露节点从公网断开。她希望你能帮忙计算,断开哪个节点能够使最终被入侵的节点数量最少。如果有多个答案,则输出编号最小的节点。

输入格式

第一行包含一个正整数 N N N,表示网络中节点的数量。

接下来 N N N 行,每行包含 N N N 个空格分隔的整数,表示矩阵 m a t r i x matrix matrix

最后一行包含若干个空格分隔的整数,表示数组 e x p o s e d exposed exposed

输出格式

输出一个整数,表示应该断开的节点编号。

样例输入

4
1 0 0 0
0 1 2 0
0 1 1 4
0 0 3 1
1 3

样例输出

3

数据范围

  • 2 ≤ N ≤ 24 2\le N\le 24 2N24
  • 0 ≤ m a t r i x [ i ] [ j ] ≤ 10 0\le matrix[i][j]\le 10 0matrix[i][j]10
  • 0 ≤ e x p o s e d [ i ] < N 0\le exposed[i]<N 0exposed[i]<N

【题目解析】

这个问题可以通过模拟攻击来解决。首先,我们需要遍历每个可能的断开的节点,然后模拟从公网入侵并在网络内部传播的过程,最终统计每个节点被入侵的次数。最后,选择使得被入侵节点数量最少的节点进行断开。

cpp

#include <iostream>
#include <vector>
#include <climits>

using namespace std;

int simulateAttack(vector<vector<int>>& matrix, vector<int>& exposed, int disconnected_node) {
    int n = matrix.size();
    vector<bool> visited(n, false);
    vector<int> permissions(n, INT_MAX);


    for (int i = 0; i < n; ++i) {
        matrix[i][disconnected_node] = 0;
    }


    int exposed_count = 0;
    for (int ex_node : exposed) {
        if (!visited[ex_node]) {
            exposed_count++;
            visited[ex_node] = true;
            permissions[ex_node] = 10;
            for (int i = 0; i < n; ++i) {
                if (matrix[ex_node][i] != 0 && matrix[ex_node][i] <= permissions[ex_node]) {
                    permissions[i] = min(permissions[i], matrix[ex_node][i]);
                }
            }
        }
    }

    for (int i = 0; i < n; ++i) {
        if (!visited[i]) {
            for (int ex_node : exposed) {
                if (matrix[i][ex_node] != 0 && matrix[i][ex_node] <= permissions[ex_node]) {
                    visited[i] = true;
                    exposed_count++;
                    break;
                }
            }
        }
    }

    return exposed_count;
}

int main() {
    int n;
    cin >> n;

    // Read matrix
    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];
        }
    }

    // Read exposed nodes
    vector<int> exposed;
    int node;
    while (cin >> node) {
        exposed.push_back(node);
    }

    // Find the node to disconnect
    int min_exposed_count = INT_MAX;
    int disconnect_node = -1;
    for (int i = 0; i < n; ++i) {
        int exposed_count = simulateAttack(matrix, exposed, i);
        if (exposed_count < min_exposed_count) {
            min_exposed_count = exposed_count;
            disconnect_node = i;
        }
    }

    cout << disconnect_node << endl;

    return 0;
}

整理试题不易,你的关注是我更新的最大动力!关注博主 带你看更多面试及竞赛试题和实用算法。

  • 19
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
华为机试真题题库提供了100道算法题,并提供了正确法和题思路。这些题目是华为机试真题,大概率会考到原题。如果你有任何问题,可以在题库中留言进行交流和探讨。 华为机试一般有三道算法题,其中前两道属于简单或中等难度,分值为100分。第三道题目为中等或困难难度,分值为200分。总分为400分,答题时间为150分钟。过去通过150分即可,但现在分数要求可能有所提高。不管怎样,大家都要努力刷题,争取拿高分。分数越高,评级就越高,工资待遇也越高。一般工资待遇是15K~30K*14~16,非常可观。 此外,如果你对华为机试真题感兴趣,我还邀请你一同入驻我的博客。我的博客即将同步至腾讯云开发者社区,你可以在那里找到更多的资源和信息。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [华为OD机试真题2022(JavaScript)](https://blog.csdn.net/weixin_40767375/article/details/125276961)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [2023年华为笔试面试机考真题100道(C/C++语言)](https://blog.csdn.net/weixin_38815609/article/details/125658519)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值