🍭 大家好这里是KK爱Coding ,一枚热爱算法的程序员
✨ 本系列打算持续跟新华为近期的春秋招笔试题汇总~
💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导
👏 感谢大家的订阅➕ 和 喜欢💗
📧 KK这边最近正在收集近一年互联网各厂的笔试题汇总,如果有需要的小伙伴可以关注后私信一下 KK领取,会在飞书进行同步的跟新。
文章目录
- 🔮01.扑克牌消消乐
- 题目描述
- 输入格式
- 输出格式
- 样例输入
- 样例输出
- 数据范围
- 题解
- 参考代码
- ⚗️02.公司部门风险评估
- 题目描述
- 输入格式
- 输出格式
- 样例输入
- 样例输出
- 数据范围
- 题解
- 参考代码
- 🎀 03.城市应急疏散
- 题目描述
- 输入格式
- 输出格式
- 样例输入
- 样例输出
- 数据范围
- 题解
- 参考代码
- 写在最后
- 📧 KK这边最近正在收集近一年互联网各厂的笔试题汇总,如果有需要的小伙伴可以关注后私信一下 KK领取,会在飞书进行同步的跟新。
本次华为的笔试不算难哦,虽然考试的时候题目长了点,但总体代码和思维量都不大
🔮01.扑克牌消消乐
题目描述
K小姐最近沉迷于一款扑克牌消除游戏。游戏规则如下:从一副扑克牌中随机抽取 n n n 张牌组成一个序列,如果有连续的 3 3 3 张相同牌号的卡牌,则这 3 3 3 张卡牌可以消除。消除后,剩余卡牌按照当前顺序重新合并成新的序列,继续寻找可以消除的卡牌组合,直到无法再消除为止。
需要注意的是,如果存在连续的 4 4 4 张相同牌号的卡牌,在消除后会剩余 1 1 1 张该牌号的卡牌。
现在,K小姐想知道最后剩余的卡牌序列是什么样的,你能帮助她吗?
输入格式
第一行包含一个正整数 n n n( 1 ≤ n ≤ 52 1 \leq n \leq 52 1≤n≤52),表示抽取的卡牌数量。
第二行包含 n n n 个以空格分隔的字符串,表示抽取的卡牌序列,卡牌号仅包含 2 2 2- 10 10 10, A A A, J J J, Q Q Q, K K K。
输出格式
输出一个字符串,表示最终剩余的卡牌号序列,卡牌号之间以空格分隔。如果最终没有卡牌剩余,则输出 0 0 0。
样例输入
10
3 A 2 2 2 A A 7 7 7
样例输出
3
数据范围
- 1 ≤ n ≤ 52 1 \leq n \leq 52 1≤n≤52
- 卡牌号仅包含 2 2 2- 10 10 10, A A A, J J J, Q Q Q, K K K。
题解
这是一道模拟题,可以使用栈来模拟卡牌的消除过程。具体步骤如下:
- 将输入的卡牌序列依次放入栈中。
- 在放入每张卡牌时,检查栈顶是否存在与当前卡牌相同的牌号。
- 如果存在,则统计相同牌号的数量,直到栈顶的卡牌牌号不同或栈为空为止。
- 如果相同牌号的数量等于 3 3 3,则将这 3 3 3 张卡牌从栈中弹出。
- 重复步骤 2 2 2,直到所有卡牌都放入栈中。
- 最后,将栈中剩余的卡牌依次输出,如果栈为空,则输出 0 0 0。
时间复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( n ) O(n) O(n)。
参考代码
- Python
n = int(input())
cards = input().split()
stack = []for card in cards:stack.append(card)while len(stack) >= 3 and stack[-1] == stack[-2] == stack[-3]:for _ in range(3):stack.pop()if not stack:print(0)
else:print(' '.join(stack))
- Java
import java.util.*;public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt();String[] cards = new String[n];for (int i = 0; i < n; i++) {cards[i] = sc.next();}List<String> stack = new ArrayList<>();for (String card : cards) {stack.add(card);int size = stack.size();while (size >= 3 && stack.get(size - 1).equals(stack.get(size - 2)) && stack.get(size - 2).equals(stack.get(size - 3))) {for (int i = 0; i < 3; i++) {stack.remove(size - 1);size--;}}}if (stack.isEmpty()) {System.out.println(0);} else {System.out.println(String.join(" ", stack));}}
}
- Cpp
#include <iostream>
#include <vector>
#include <string>using namespace std;int main() {int n;cin >> n;vector<string> cards(n);for (int i = 0; i < n; i++) {cin >> cards[i];}vector<string> stack;for (string card : cards) {stack.push_back(card);int size = stack.size();while (size >= 3 && stack[size - 1] == stack[size - 2] && stack[size - 2] == stack[size - 3]) {for (int i = 0; i < 3; i++) {stack.pop_back();size--;}}}if (stack.empty()) {cout << 0 << endl;} else {for (int i = 0; i < stack.size(); i++) {cout << stack[i] << " \n"[i == stack.size() - 1];}}return 0;
}
⚗️02.公司部门风险评估
题目描述
LYA 是一家大型科技公司的风险评估师。公司的部门结构可以看作一棵树,每个部门在评估前都有一些尚未解决的问题。部门的风险值可以用来评估该部门是否存在风险,风险值的计算公式为: 风险值 = 5 × 严重问题数 + 2 × 一般问题数 风险值 = 5 \times 严重问题数 + 2 \times 一般问题数 风险值=5×严重问题数+2×一般问题数。
其中,每个部门的不同级别问题数量需要将该部门及其下属部门的相应级别问题数量求和。当部门的风险值小于等于给定的阈值时,该部门被认为是安全的;否则,该部门被视为风险部门,需要进一步整改。
现在给出公司的部门结构以及各部门的问题数量,请你帮助 LYA 计算出风险部门的数量。
输入格式
第一行包含两个正整数 M M M 和 N N N( 1 ≤ M ≤ 100000 1 \leq M \leq 100000 1≤M≤100000, 1 ≤ N ≤ 1000 1 \leq N \leq 1000 1≤N≤1000),分别表示风险阈值和部门的数量。
接下来 N N N 行,每行包含四个字段,用空格分隔:
- 第一个字段为部门名称 A i A_i Ai;
- 第二个字段为 A i A_i Ai 的上级部门名称 B i B_i Bi,如果 A i A_i Ai 为公司的最高层部门,则 B i B_i Bi 用
*
表示; - 第三个字段为问题级别 C i C_i Ci( C i ∈ { 0 , 1 } C_i \in \{0, 1\} Ci∈{0,1},其中 0 0 0 表示严重问题, 1 1 1 表示一般问题);
- 第四个字段为该部门该级别的问题数量 D i D_i Di( 1 ≤ D i ≤ 1000 1 \leq D_i \leq 1000 1≤Di≤1000)。
其中, A i A_i Ai 和 B i B_i Bi 为由小写英文字母组成的字符串,长度不超过 5 5 5。
输入保证部门结构为一棵树,不会出现环的情况。
输出格式
输出一个整数,表示风险部门的数量。
样例输入
40 12
a * 0 2
a * 1 2
b a 0 3
b a 1 5
c a 1 3
d a 0 1
d a 1 3
e b 0 2
f * 0 8
f * 1 10
g f 1 2
h * 0 4
样例输出
2
数据范围
- 1 ≤ M ≤ 100000 1 \leq M \leq 100000 1≤M≤100000
- 1 ≤ N ≤ 1000 1 \leq N \leq 1000 1≤N≤1000
- 1 ≤ D i ≤ 1000 1 \leq D_i \leq 1000 1≤Di≤1000
- A i A_i Ai 和 B i B_i Bi 为由小写英文字母组成的字符串,长度不超过 5 5 5。
题解
本题可以使用树形 DP 的思想来解决。可以从叶子节点开始,自底向上计算每个部门的严重问题数和一般问题数,然后根据风险值的计算公式判断该部门是否为风险部门。
具体步骤如下:
- 建立部门之间的父子关系,使用邻接表或者邻接矩阵来存储。
- 对于每个部门,初始化其严重问题数和一般问题数。
- 从叶子节点开始,通过 DFS 或 BFS 遍历整棵树,对于每个部门:
- 将其子部门的严重问题数和一般问题数累加到当前部门上。
- 计算当前部门的风险值,并判断是否超过阈值,如果超过则将风险部门数量加 1 1 1。
- 输出风险部门的数量。
时间复杂度为 O ( N ) O(N) O(N),空间复杂度为 O ( N ) O(N) O(N),其中 N N N 为部门的数量。
参考代码
- Python
from collections import defaultdictdef dfs(dept):risk1, risk2 = risks1[dept], risks2[dept]for sub in graph[dept]:sub_risk1, sub_risk2 = dfs(sub)risk1 += sub_risk1risk2 += sub_risk2return risk1, risk2m, n = map(int, input().split())
graph = defaultdict(list)
risks1 = defaultdict(int)
risks2 = defaultdict(int)roots = set()
for _ in range(n):dept, parent, level, num = input().split()num = int(num)if parent == '*':roots.add(dept)else:graph[parent].append(dept)if level == '0':risks1[dept] = numelse:risks2[dept] = numcnt = 0
for root in roots:risk1, risk2 = dfs(root)if 5 * risk1 + 2 * risk2 > m:cnt += 1print(cnt)
- Java
import java.util.*;public class Main {static Map<String, List<String>> graph = new HashMap<>();static Map<String, Integer> risks1 = new HashMap<>();static Map<String, Integer> risks2 = new HashMap<>();public static void main(String[] args) {Scanner sc = new Scanner(System.in);int m = sc.nextInt();int n = sc.nextInt();sc.nextLine();Set<String> roots = new HashSet<>();for (int i = 0; i < n; i++) {String[] input = sc.nextLine().split(" ");String dept = input[0];String parent = input[1];int level = Integer.parseInt(input[2]);int num = Integer.parseInt(input[3]);if (parent.equals("*")) {roots.add(dept);} else {graph.computeIfAbsent(parent, k -> new ArrayList<>()).add(dept);}if (level == 0) {risks1.put(dept, num);} else {risks2.put(dept, num);}}int cnt = 0;for (String root : roots) {int[] risks = dfs(root);if (5 * risks[0] + 2 * risks[1] > m) {cnt++;}}System.out.println(cnt);}private static int[] dfs(String dept) {int risk1 = risks1.getOrDefault(dept, 0);int risk2 = risks2.getOrDefault(dept, 0);for (String sub : graph.getOrDefault(dept, new ArrayList<>())) {int[] subRisks = dfs(sub);risk1 += subRisks[0];risk2 += subRisks[1];}return new int[]{risk1, risk2};}
}
- Cpp
#include <iostream>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <string>using namespace std;unordered_map<string, vector<string>> graph;
unordered_map<string, int> risks1;
unordered_map<string, int> risks2;pair<int, int> dfs(const string& dept) {int risk1 = risks1[dept];int risk2 = risks2[dept];for (const string& sub : graph[dept]) {auto subRisks = dfs(sub);risk1 += subRisks.first;risk2 += subRisks.second;}return {risk1, risk2};
}int main() {int m, n;cin >> m >> n;unordered_set<string> roots;for (int i = 0; i < n; i++) {string dept, parent;int level, num;cin >> dept >> parent >> level >> num;if (parent == "*") {roots.insert(dept);} else {graph[parent].push_back(dept);}if (level == 0) {risks1[dept] = num;} else {risks2[dept] = num;}}int cnt = 0;for (const string& root : roots) {auto risks = dfs(root);if (5 * risks.first + 2 * risks.second > m) {cnt++;}}cout << cnt << endl;return 0;
}
🎀 03.城市应急疏散
题目描述
LYA 是一名城市应急管理专家,她负责制定城市在发生重大事故时的疏散计划。城市由 n n n 个区域组成,每个区域之间都有道路相连。当某个区域发生事故需要疏散时,LYA 需要选择一个或多个安全区域作为疏散目的地,并确保疏散路径的总长度最短。
给定一个 n × n n \times n n×n 的矩阵 d i s t dist dist,其中 d i s t [ i ] [ j ] dist[i][j] dist[i][j] 表示区域 i i i 到区域 j j j 的道路长度,如果 d i s t [ i ] [ j ] = − 1 dist[i][j] = -1 dist[i][j]=−1,则表示区域 i i i 和区域 j j j 之间没有直接相连的道路。另外,每个区域还有一个剩余容量 c a p [ i ] cap[i] cap[i],表示该区域最多可以容纳的人数。
当某个区域 x x x 发生事故需要疏散人数为 p p p 时,请你帮助 LYA 选择疏散区域,使得疏散路径的总长度最短,并且疏散区域的剩余容量之和不小于 p p p。如果有多个疏散区域到事故区域的最短路径长度相同,则优先选择编号较小的区域。
输入格式
第一行包含一个正整数 n n n,表示区域的数量。
接下来 n n n 行,每行包含 n n n 个整数,表示矩阵 d i s t dist dist。
接下来一行包含 n n n 个整数,表示每个区域的剩余容量 c a p [ i ] cap[i] cap[i]。
最后一行包含两个整数 x x x 和 p p p,分别表示发生事故的区域编号和需要疏散的人数。
输出格式
输出一行,包含若干个整数,表示选择的疏散区域编号。如果有多个疏散区域到事故区域的最短路径长度相同,则按照编号从小到大的顺序输出。
样例输入
4
-1 5 -1 8
5 -1 1 3
-1 1 -1 4
8 3 4 -1
10 20 15 25
2 12
样例输出
1
数据范围
- 2 ≤ n ≤ 1 0 4 2 \leq n \leq 10^4 2≤n≤104
- − 1 ≤ d i s t [ i ] [ j ] ≤ 1000 -1 \leq dist[i][j] \leq 1000 −1≤dist[i][j]≤1000
- 1 ≤ c a p [ i ] ≤ 100 1 \leq cap[i] \leq 100 1≤cap[i]≤100
- 0 ≤ x < n 0 \leq x < n 0≤x<n
- 0 < p ≤ 1000 0 < p \leq 1000 0<p≤1000
题解
本题可以使用 Dijkstra 算法求出事故区域到其他所有区域的最短路径长度,然后将区域按照最短路径长度从小到大排序,依次选择区域作为疏散目的地,直到选择的区域剩余容量之和不小于需要疏散的人数为止。
具体步骤如下:
- 使用 Dijkstra 算法求出事故区域到其他所有区域的最短路径长度,记为 d [ i ] d[i] d[i]。
- 将区域按照 ( d [ i ] , c a p [ i ] , i ) (d[i], cap[i], i) (d[i],cap[i],i) 的顺序从小到大排序,其中 d [ i ] d[i] d[i] 为最短路径长度, c a p [ i ] cap[i] cap[i] 为剩余容量, i i i 为区域编号。
- 依次选择排序后的区域作为疏散目的地,直到选择的区域剩余容量之和不小于需要疏散的人数为止。
- 输出选择的疏散区域编号。
时间复杂度 O ( n 2 + n log n ) O(n^2 + n \log n) O(n2+nlogn),空间复杂度 O ( n 2 ) O(n^2) O(n2)。其中 n n n 为区域的数量。
参考代码
- Python
import heapqn = int(input())
dist = [list(map(int, input().split())) for _ in range(n)]
cap = list(map(int, input().split()))
x, p = map(int, input().split())for i in range(n):for j in range(n):if dist[i][j] == -1:dist[i][j] = float('inf')d = [float('inf')] * n
d[x] = 0
q = [(0, x)]while q:_, u = heapq.heappop(q)for v in range(n):if d[u] + dist[u][v] < d[v]:d[v] = d[u] + dist[u][v]heapq.heappush(q, (d[v], v))regions = sorted([(d[i], cap[i], i) for i in range(n) if i != x])ans = []
total_cap = 0
for _, c, i in regions:if total_cap >= p:breakans.append(i)total_cap += cprint(*ans)
- Java
import java.util.*;public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt();int[][] dist = new int[n][n];for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {dist[i][j] = sc.nextInt();if (dist[i][j] == -1) {dist[i][j] = Integer.MAX_VALUE;}}}int[] cap = new int[n];for (int i = 0; i < n; i++) {cap[i] = sc.nextInt();}int x = sc.nextInt();int p = sc.nextInt();int[] d = new int[n];Arrays.fill(d, Integer.MAX_VALUE);d[x] = 0;PriorityQueue<int[]> q = new PriorityQueue<>((a, b) -> a[0] - b[0]);q.offer(new int[]{0, x});while (!q.isEmpty()) {int[] curr = q.poll();int u = curr[1];for (int v = 0; v < n; v++) {if (d[u] + dist[u][v] < d[v]) {d[v] = d[u] + dist[u][v];q.offer(new int[]{d[v], v});}}}List<int[]> regions = new ArrayList<>();for (int i = 0; i < n; i++) {if (i != x) {regions.add(new int[]{d[i], cap[i], i});}}regions.sort((a, b) -> {if (a[0] != b[0]) {return a[0] - b[0];}if (a[1] != b[1]) {return b[1] - a[1];}return a[2] - b[2];});List<Integer> ans = new ArrayList<>();int totalCap = 0;for (int[] region : regions) {if (totalCap >= p) {break;}ans.add(region[2]);totalCap += region[1];}for (int i = 0; i < ans.size(); i++) {System.out.print(ans.get(i));if (i < ans.size() - 1) {System.out.print(" ");}}}
}
- Cpp
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;const int INF = 0x3f3f3f3f;int main() {int n;cin >> n;vector<vector<int>> dist(n, vector<int>(n));for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {cin >> dist[i][j];if (dist[i][j] == -1) {dist[i][j] = INF;}}}vector<int> cap(n);for (int i = 0; i < n; i++) {cin >> cap[i];}int x, p;cin >> x >> p;vector<int> d(n, INF);d[x] = 0;priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q;q.emplace(0, x);while (!q.empty()) {auto [du, u] = q.top();q.pop();if (du > d[u]) {continue;}for (int v = 0; v < n; v++) {if (d[u] + dist[u][v] < d[v]) {d[v] = d[u] + dist[u][v];q.emplace(d[v], v);}}}vector<tuple<int, int, int>> regions;for (int i = 0; i < n; i++) {if (i != x) {regions.emplace_back(d[i], cap[i], i);}}sort(regions.begin(), regions.end());vector<int> ans;int total_cap = 0;for (auto [di, ci, i] : regions) {if (total_cap >= p) {break;}ans.push_back(i);total_cap += ci;}for (int i = 0; i < ans.size(); i++) {cout << ans[i];if (i < ans.size() - 1) {cout << " ";}}cout << endl;return 0;
}
写在最后
📧 KK这边最近正在收集近一年互联网各厂的笔试题汇总,如果有需要的小伙伴可以关注后私信一下 KK领取,会在飞书进行同步的跟新。