🍭 大家好这里是KK爱Coding ,一枚热爱算法的程序员
✨ 本系列打算持续跟新华为近期的春秋招笔试题汇总~
💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导
👏 感谢大家的订阅➕ 和 喜欢💗
📧 KK这边最近正在收集近一年互联网各厂的笔试题汇总,如果有需要的小伙伴可以关注后私信一下 KK领取,会在飞书进行同步的跟新。
💻 前言
🍭 关于华为
- 据说今晚有华为的机试啦,华为的春招也算是正式开始了,关于华为的笔试,大家可以自由选时间去安排,大致时间就是每周三,具体哪一周需要自己去做决定,和 HR 沟通或者邮件📧反馈,一般会有 HR 联系你修改信息,包括后面笔试的成绩,也可以问 HR ,华为的 HR 是真滴很不错 👍
📓 笔试要求
- 华为的笔试有个硬性规定,笔试分是需要达到 150/600 分才算是通过,三道题目的构成分数构成为
100
,200
,300
分,后续的面试流程会根据笔试成绩来进行排序哦。
🪜 笔试技巧
笔试的思维破局
- 之前写别的公司机试的小伙伴一般都是按照顺序来写的,因为越往后的题目难度越高,这样会形成一个惯性,做每家公司的笔试都这么干。
- 但华为题目的代码编写难易度并不一定是递进的,比如
第一题
可能是题意很简单,但是码量很大。第三题
可能代码随便写几行就能拿到很多分,大家在机试的时候需要把把握好做题的顺序,每道题可以都先过一遍。
骗分技巧
- 适当使用暴力骗分,如果对于当前这题没有什么想法,不要多想直接写暴力或许能拿到不少的分数。
- 对于题目要求输出
Yes
orNo
,或者无解输出-1
的情况,那么可以试试直接输出,一般也能拿到一些分数 - 这里捞一点那里骗一点,说不定就够
150
分了哦
🥰 题目练手
那么本次就给大家带来去年秋招的华为的真题练练手,祝大家今晚发挥超长,笔试 AK !! !!
文章目录
_________________________________________
✈️ 笔试题目
🍋 01.网络连通性分析
问题描述
K小姐是一名网络工程师,她搭建了一个复杂的网络系统。在这个网络系统中,一共有 N N N 个节点,每个节点都有一个独一无二的标识,我们称之为节点名。每个节点拥有 t t t 个端口,这些端口用于节点之间的报文传输。为了管理网络,K小姐将所有端口分配了一个连通块编号(用 id 表示)。
连通性规则如下:
- 若两个端口的 id 相同,则它们属于同一个连通块,这两个端口是连通的。
- 若两个端口的 id 不同,则它们不连通。
现在,K小姐想要知道,哪些节点与特定的节点 A 是连通的,即通过至少一个端口与节点 A 属于同一个连通块。
输入格式
第一行包含一个整数 m m m 和 m m m 个整数,代表节点 A 的端口数量以及每个端口的 id。
第二行包含一个整数 n n n,代表除节点 A 之外网络中的其他节点数量。
接下来的 n n n 行,每行的格式为: N a m e t i d 1 i d 2 . . . i d t Name\ t\ id_1\ id_2\ ...\ id_t Name t id1 id2 ... idt
输出格式
第一行输出一个整数 N N N,代表与节点 A 连通的节点的总数。
第二行输出 N N N 个整数,按照节点的 N a m e Name Name 从小到大排序。
样例输入
2 1 2
4
1000 3 4 3 5
1001 2 1 2
114514 3 1 2 3
1919810 1 1
样例输出
3
1001 114514 1919810
数据范围
- 0 ≤ n ≤ 4000 0 \le n \le 4000 0≤n≤4000
- 1 ≤ N a m e ≤ 4294967294 1 \le Name \le 4294967294 1≤Name≤4294967294
题解
要解决这个问题,我们需要创建一个集合来存储节点 A 的所有端口 id。然后,遍历每个其他节点的端口,如果某个端口的 id 在节点 A 的端口 id 集合中,那么这个节点就与节点 A 连通。我们将所有连通的节点收集起来并排序输出。
参考代码
- Python
n, *a_ids = map(int, input().split())
count = int(input())
connected_nodes = []
for _ in range(count):
name, t, *ids = map(int, input().split())
if set(ids).intersection(a_ids):
connected_nodes.append(name)
print(len(connected_nodes))
print(' '.join(map(str, sorted(connected_nodes))))
- Java
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int m = scanner.nextInt();
Set<Integer> setA = new HashSet<>();
for (int i = 0; i < m; i++) {
setA.add(scanner.nextInt());
}
int n = scanner.nextInt();
List<Integer> connectedNodes = new ArrayList<>();
for (int i = 0; i < n; i++) {
int name = scanner.nextInt();
int t = scanner.nextInt();
boolean isConnected = false;
for (int j = 0; j < t; j++) {
if (setA.contains(scanner.nextInt())) {
isConnected = true;
}
}
if (isConnected) {
connectedNodes.add(name);
}
}
Collections.sort(connectedNodes);
System.out.println(connectedNodes.size());
connectedNodes.forEach(name -> System.out.print(name + " "));
System.out.println();
}
}
- Cpp
#include <iostream>
#include <unordered_set>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
int m, n, id, name, t;
cin >> m;
unordered_set<int> aPorts;
for (int i = 0; i < m; ++i) {
cin >> id;
aPorts.insert(id);
}
cin >> n;
vector<unsigned int> connectedNodes;
for (int i = 0; i < n; ++i) {
bool isConnected = false;
cin >> name >> t;
for (int j = 0; j < t; ++j) {
cin >> id;
if (aPorts.find(id) != aPorts.end()) {
isConnected = true;
}
}
if (isConnected) {
connectedNodes.push_back(name);
}
}
sort(connectedNodes.begin(), connectedNodes.end());
cout << connectedNodes.size() << endl;
for (const auto &node : connectedNodes) {
cout << node << " ";
}
cout << endl;
return 0;
}
🍎 02.K小姐的文本编辑器
题目描述
K小姐最近在开发一款文本编辑器,她希望这个编辑器能够实现一些基本的文本操作功能。这款编辑器需要支持以下操作:
insert str
:在当前光标位置插入字符串 s t r str str,并将光标移动到插入的字符串的末尾。delete len
:删除光标左侧长度为 l e n len len 的字符串。如果 l e n < 0 len \lt 0 len<0 或者 l e n len len 大于光标左侧的字符串长度,则不进行操作。move cnt
:将光标移动 c n t cnt cnt 个位置。如果 c n t cnt cnt 为负数,则向左移动;如果 c n t cnt cnt 为正数,则向右移动。如果 c n t cnt cnt 超出字符串的边界,则不进行移动。copy
:将光标左侧的字符串复制并插入到光标的右侧,光标位置保持不变。
现在,K小姐已经完成了这款文本编辑器的开发,你正在进行测试。给定一系列操作命令,请你输出执行这些操作后得到的最终文本内容。
输入格式
输入由多行组成,每行包含一个操作命令。操作命令的格式如题目描述所示。
输入以 end
结束,表示操作结束。
初始时,文本内容为空,光标位置为
0
0
0。
输出格式
输出执行所有操作后得到的最终文本内容。
请用 |
表示光标的位置。
样例输入
insert test
insert pass
move 10
delete 4
insert fail
move -4
copy
end
样例输出
test|testfail
数据范围
- 1 ≤ s t r . l e n g t h ≤ 40 1 \le str.length \le 40 1≤str.length≤40
- 1 ≤ l e n ≤ 40 1 \le len \le 40 1≤len≤40
- − 40 ≤ c n t ≤ 40 -40 \le cnt \le 40 −40≤cnt≤40
insert
、delete
、move
和copy
操作的总次数不超过 200 200 200 次。
题解
本题可以使用双端队列(deque)来模拟文本编辑器的操作。我们可以将光标左侧的字符存储在一个双端队列 front
中,将光标右侧的字符存储在另一个双端队列 back
中。
对于 insert
操作,我们将要插入的字符串压入 front
的尾部。
对于 delete
操作,我们从 front
的尾部弹出
l
e
n
len
len 个字符。
对于 move
操作,如果
c
n
t
cnt
cnt 为负数,我们将 front
尾部的字符弹出并压入 back
的头部,重复
−
c
n
t
-cnt
−cnt 次;如果
c
n
t
cnt
cnt 为正数,我们将 back
头部的字符弹出并压入 front
的尾部,重复
c
n
t
cnt
cnt 次。
对于 copy
操作,我们将 front
中的字符依次弹出并压入 back
的头部。
最后,我们将 front
和 back
中的字符拼接起来,并在中间插入 |
表示光标位置,即可得到最终的文本内容。
时间复杂度:
O
(
n
)
O(n)
O(n),其中
n
n
n 为操作的总次数。每个操作的时间复杂度为
O
(
1
)
O(1)
O(1)。
空间复杂度:
O
(
m
)
O(m)
O(m),其中
m
m
m 为最终文本内容的长度。
参考代码
- Java
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
Deque<Character> front = new ArrayDeque<>();
Deque<Character> back = new ArrayDeque<>();
while (sc.hasNext()) {
String[] op = sc.nextLine().split(" ");
if (op[0].equals("end")) {
break;
} else if (op[0].equals("insert")) {
for (char c : op[1].toCharArray()) {
front.offerLast(c);
}
} else if (op[0].equals("delete")) {
int len = Integer.parseInt(op[1]);
while (len > 0 && len <= front.size()) {
front.pollLast();
len--;
}
} else if (op[0].equals("move")) {
int cnt = Integer.parseInt(op[1]);
while (cnt < 0 && -cnt <= front.size()) {
back.offerFirst(front.pollLast());
cnt++;
}
while (cnt > 0 && cnt <= back.size()) {
front.offerLast(back.pollFirst());
cnt--;
}
} else if (op[0].equals("copy")) {
Deque<Character> temp = new ArrayDeque<>(front);
while (!temp.isEmpty()) {
back.offerFirst(temp.pollLast());
}
}
}
StringBuilder sb = new StringBuilder();
for (char c : front) {
sb.append(c);
}
sb.append("|");
for (char c : back) {
sb.append(c);
}
System.out.println(sb.toString());
}
}
🍌 03.K小姐的魔法镜阵
问题描述
K小姐收集了一些神奇的魔法镜,这些镜子可以吸收魔法光芒,并在一定时间后将光芒向四周散射。
这些魔法镜分为一级镜和二级镜两种类型。一级镜的散射速度较快,仅需 1 1 1 毫秒就能将光芒向上下左右四个方向散射;而二级镜则需要 2 2 2 毫秒才能完成散射。
K小姐将这些魔法镜按照整数坐标排列在一个二维矩阵中。现在,她在某个位置的魔法镜上施加了一道魔法光芒,想知道最早什么时候所有的魔法镜都能吸收到这道光芒。
注意:矩阵的下标从 0 0 0 开始。
输入格式
第一行包含两个正整数 n n n 和 m m m,分别表示矩阵的列数和行数,满足 1 ≤ n , m ≤ 500 1 \le n,m \le 500 1≤n,m≤500。
第二行包含两个正整数 i i i 和 j j j,表示最初获得光芒的魔法镜的坐标。
接下来 m m m 行,每行包含 n n n 个整数,表示该位置魔法镜的等级:
- 如果为 0 0 0,表示该位置是一堵密不透光的墙,它可以完全阻挡光芒的传播。
- 如果为 1 1 1,表示该位置的魔法镜散射耗时 1 1 1 毫秒。
- 如果为 2 2 2,表示该位置的魔法镜散射耗时 2 2 2 毫秒。
输出格式
输出一个整数,表示所有魔法镜都能吸收到光芒所需的最小时间。如果有些魔法镜无法吸收到光芒,则输出 − 1 -1 −1。
样例输入
5
5
2 2
1 0 2 1 0
2 2 1 2 0
0 0 1 0 0
2 1 1 0 0
1 1 1 1 1
样例输出
6
数据范围
1
≤
n
,
m
≤
500
1 \le n,m \le 500
1≤n,m≤500
0
≤
i
<
m
0 \le i < m
0≤i<m
0
≤
j
<
n
0 \le j < n
0≤j<n
题解
本题可以使用最短路算法(如Dijkstra算法)来求解。
我们可以将每个位置看作图中的一个节点,如果两个相邻位置间没有墙阻隔,则它们之间存在一条边,边的权重为该位置魔法镜的散射时间。
然后,从起始位置开始,使用Dijkstra算法计算到达每个位置的最短时间。在算法过程中,我们可以记录下最长的最短时间,即为所有魔法镜都吸收到光芒所需的最小时间。
如果在算法结束后,仍有位置的最短时间为无穷大,说明该位置无法被光芒照射到,此时输出 − 1 -1 −1。
算法的时间复杂度为 O ( n m log n m ) O(nm \log nm) O(nmlognm),空间复杂度为 O ( n m ) O(nm) O(nm)。
参考代码
- Python
import heapq
n = int(input())
m = int(input())
start_x, start_y = map(int, input().split())
matrix = [list(map(int, input().split())) for _ in range(m)]
dist = [[10 ** 9] * n for _ in range(m)]
visited = [[False] * n for _ in range(m)]
dx = [1, -1, 0, 0]
dy = [0, 0, 1, -1]
dist[start_x][start_y] = 0
pq = [(0, start_x, start_y)]
while pq:
d, x, y = heapq.heappop(pq)
if visited[x][y]:
continue
visited[x][y] = True
for i in range(4):
nx, ny = x + dx[i], y + dy[i]
if 0 <= nx < m and 0 <= ny < n and matrix[nx][ny] != 0:
new_dist = d + matrix[x][y]
if new_dist < dist[nx][ny]:
dist[nx][ny] = new_dist
heapq.heappush(pq, (new_dist, nx, ny))
ans = 0
for i in range(m):
for j in range(n):
if matrix[i][j] != 0:
ans = max(ans, dist[i][j])
print(ans if ans != 10 ** 9 else -1)
🍍 写在最后
📧 KK这边最近正在收集近一年互联网各厂的笔试题汇总,如果有需要的小伙伴可以关注后私信一下 KK领取,会在飞书进行同步的跟新。