华为1025秋招笔试真题解析
- 2026-10-30 19:48:37
关注我们,每周更新两到三次大厂最新笔试题解析
前言
难度比较大,大量的复杂模拟,非常考验代码能力。华子每年基本都是一样的德性,越往后题目就越魔鬼,后面笔试的同学要好好加油啊(最近还没做笔试的同学,非常建议学一手python,面对这种大字符串的模拟,cpp和Java是真的很无力)
指出简化版本xml字符串的错误
正常的xml样例如下:
<book>
<author>Cay s. Horstmann</author>
<isbn lang="CN">1234567</isbn>
<tags>
<tag>java</tag>
<tag>Network</tag>
</tags>
<pubDate/>
</book>
xml必须包含根节点,book就样例中的根节点。xml节点可以嵌套:如book和tags节点
简化版xml节点满足如下条件
1.节点的名称为单字符,如<a></a>,不会出现<ab></ab>
2.节点不带属性
3.节点不会出现<a/>
4.节点会出现带值情况如<a>Value</a>
5.xml节点包含值和包含子节点。只能二选一。
请计算给定简化版xml字符串中不合规的当前节点名称。不合规的当前节点:是指当前xml节点node1与下一个xml节点node2不匹配,则node1节点为当前节点。
题目保证输入的简化版xml,有且只有一个错误。
解答要求
时间限制: C/C++ 1000ms,其他语言: 2000ms 内存限制: C/C++ 256MB,其他语言:512MB
输入
简化版xml字符串,长度为小于1000.省略了样例中的换行符。
输出
输出给定简化版xml字符串中不合规的当前节点名称。
样例1
输入
<a><b></a>
输出
b
思路与代码
字符串模拟+栈。
1.首先将标签分割开来,这里将 ">"处理成"> "(多了个括号),以及"<"处理成" <",然后使用split函数按照空格分割即可。
2.栈模拟,遇到左标签则进栈,否则出栈直到匹配为止。切记要统计标签之间的元素梳理是否满足最多只有一个。
s = input()
s = s.replace("<"," <")
s = s.replace(">","> ")
s = s.strip()
arr = s.split(" ")
for i in arr:
if i == '':
arr.remove(i)
def solve():
sk = []
def proce(s):
return s.replace("<","").replace("/","").replace(">","")
for a in arr:
if a[:2] == "</":
cnt = 0
while sk and sk[-1] != a.replace("/", ""):
tp = sk.pop()
if tp[0] == '<':
print(proce(tp))
return
cnt += 1
if sk[-1] == a.replace("/", ""):
sk.pop()
if cnt > 1:
print(proce(a))
return
else:
if sk and sk[-1][0] != '<':
#栈顶元素不为左标签
print(proce(sk[-2]))
return
sk.append(a)
solve()
实现一个简易版的消息分发程序
实习一个简易版的消息分发程序,客户端可以广播消息,可以订阅和取消订阅其他用户(默认订阅了自己)
每一个客户端有一个ClientID,每一条消息都有一个MsgID。请实现如下方法。
| 序号 | 方法 | 返回值 | 说明 |
|---|---|---|---|
| 1 | Brocast(ClientID,MsgID) | 返回发送的消息条数 | ID为ClientID的客户端广播了一条ID为MsgID的新消息 |
| 2 | GetMsg(ClientID, N) | 返回最近的N条消息 | 获取ID为 clientID 的客户端的消息,技消息出现的先后顺序排列,如果不够N条,按实际条数输出,一条消息都没有,输出-1 |
| 3 | Subscribe(ClientiD1,ClientiD2) | 返回订阅状态,0表示正常订阅,1表示重复订阅,2表示自己订阅自己 | ID为 clientID1的客户端1订阅ID为 clientID2的客户端2的消息,即客户端2广播的消息在客户端1订阅后,就会被其接收到 |
| 4 | UnSubscribe(ClientiD1,ClientiD2) | 返回取消订阅状态,0表示正常取消,其他值(1和2表示取消失败,1表示败原因是不存在此订阅关系,2表示失败原因是自己无法取消订阅自己. | ID为 clientID1的客户端1取消订阅ID为 clientID2的客户端2的消息,即客户端2广播的消息在客户端1取消订阅后,就从客户端1的消息里删除 |
指令按时间顺序输入,且客户端广播的消息都被系统记录不会消失,订阅生效后,能够查询到目标客户端的之前发送的消息
解答要求
时间限制: C/C++ 1000ms,其他语言: 2000ms 内存限制: C/C++ 256MB,其他语言:512MB
输入
每行一条指令,每条指令包含指令名称和指令参数(可选), 并中间用一个空格隔开,所有的指令满足如上规则,不用处理输入格式异常,其中ClientID满足O<=ClientID<=10000000,MsgID满足O<=MsgID<=100000000。
输出
每一行输入,对应一行输出,并用单个空格隔开消息。
样例1
输入
Brocast 1 5
Brocast 2 6
GetMsg 2 10
Subcribe 2 1
GetMsg 2 10
GetMsg 3 5
输出
1
1
6
0
6 5
-1
思路与代码
字符串模拟题。
总体的思想是使用哈希表来统计每一个id的订阅以及每一个id所发送的消息。
重点注意”GetMsg“函数,需要将所有订阅的id的每一条消息加入到一个数组中,然后按照消息的先后顺序排序,取出后N条。
from collections import defaultdict
inputs = []
while True:
try:
inputs.append(input())
except:
break
sends = defaultdict(list)
subs = defaultdict(list)
index = 0
for input in inputs:
ops = input.split()
if ops[1] not in subs:
subs[ops[1]].append(ops[1])
if ops[0] == 'Brocast':
cid,msg = ops[1], ops[2]
sends[cid].append([msg, index])
print(len(sends[cid]))
elif ops[0] == 'GetMsg':
cid, N = ops[1], ops[2]
msgs = []
for s in subs[cid]:
msgs += sends[s]
if len(msgs) == 0:
print(-1)
continue
msgs.sort(key=lambda x:x[1])
res = []
for i, msg in enumerate(msgs[::-1]):
mid = msg[0]
if i == N: break
res.append(mid)
print(' '.join([str(c) for c in res]))
elif ops[0] == 'Subscribe':
cid1, cid2 = ops[1], ops[2]
if cid1 == cid2:
print(2)
continue
if cid2 in subs[cid1]:
print(1)
continue
print(0)
if cid2 not in subs[cid1]:
subs[cid1].append(cid2)
elif ops[0] == 'UnSubscribe':
cid1, cid2 = ops[1], ops[2]
if cid1 == cid2:
print(2)
continue
if cid2 not in subs[cid1]:
print(1)
continue
print(0)
if cid2 in subs[cid1]:
subs[cid1].remove(cid2)
index+=1
字母加法
给你一个字母加法公式,形如“send”+“more”=“money”,公式左侧字符串“send”、“more”为加数和被加数,公式右侧字符“money”为加数和,满足以下规则: (1)公式中每个英文字母(均为小写字母)都代表一位数字(0~9),且不同字母代表不同数字; (2)公式中每个字符串的第一个字母所代表的数字不为0,比如“send”的第一个字母不为0,“more”、“money”同理;
判断该字母公式是否成立,如果成立,返回公式右侧字符串加数和转换成数字对应的数值(如果存在多组解,返回最小的一组解) ;如果不成立,返回 -1。
解答要求
时间限制: C/C++ 300ms,其他语言: 600ms 内存限制: C/C++ 64MB,其他语言:128MB
输入
第一行为左侧加数和被加数的总个数N,范围为[2,6]
接下来N行为加数和被加数的字符串,每个字符串长度范围为[1,6]
最后一行为加数和的字符串,字符串长度范围为[1,7]
输出
有2种情况:
(1)如果字母公式成立,返回加数和转换成数字对应的数值
(2)如果字母公式不成立,返回-1
样例1
输入
2
send
more
money
输出
10336
思路与代码
模拟+回溯。
数据比较小,可以直接枚举字母和数字之间的映射关系,但是需要进行不少剪枝,否则会超时,因为可能性太多了。
以下代码引用自: https://leetcode.cn/problems/verbal-arithmetic-puzzle/solutions/1685148/er-xu-cheng-ming-jiu-xu-zui-by-liupengsa-x7eg/
from collections import defaultdict
N = int(input())
words = []
for i in range(N):words.append(input())
result = input()
def isSolvable( words, result: str):
if all(len(word) + 1 < len(result) for word in words):
return False
dct = defaultdict(int)
for word in words:
k = len(word)
for i in range(k):
dct[word[i]] += 10 ** (k - i - 1)
n = len(result)
for i in range(n):
dct[result[i]] -= 10 ** (n - i - 1)
lst = [[dct[k], k] for k in dct if dct[k]]
lst.sort(key=lambda x: abs(x[0]), reverse=True)
m = len(lst)
mapper = {}
for i in range(m):
mapper[lst[i][1]] = i
def compute_ceil_floor(rest, pos, neg):
post_ceil = 0
for r in range(len(neg)):
post_ceil += rest[r] * neg[r]
for r in range(len(pos)):
post_ceil += rest[-r - 1] * pos[r]
post_floor = 0
for r in range(len(pos)):
post_floor += rest[r] * pos[r]
for r in range(len(neg)):
post_floor += rest[-r - 1] * neg[r]
return post_ceil, post_floor
def check():
map_num = dict()
for c in range(m):
map_num[lst[c][1]] = mapping[c]
for word in words + [result]:
if len(word) >= 2:
if word[0] in map_num and map_num[word[0]] == 0:
return False
if word[0] not in map_num and m == 9 and 0 not in mapping:
return False
return True
ans = []
mapping = [-1] * m
def dfs(pre_sum, ind):
nonlocal ans
if ans:
return
if ind == m:
if not pre_sum and check():
ans = mapping[:]
return
for num in range(10):
if num not in mapping:
rest = [j for j in range(10) if j not in mapping and j != num]
rest.sort()
pos = [ls[0] for ls in lst[ind + 1:] if ls[0] > 0]
neg = [ls[0] for ls in lst[ind + 1:] if ls[0] < 0]
post_ceil, post_floor = compute_ceil_floor(rest, pos, neg)
if -post_ceil <= pre_sum + lst[ind][0] * num <= -post_floor:
mapping[ind] = num
dfs(pre_sum + lst[ind][0] * num, ind + 1)
mapping[ind] = -1
dfs(0, 0)
if ans:
print(''.join([str(ans[mapper[r]]) for r in result]))
else:print(-1)
isSolvable(words, result)
最后插一下我们的进阶一对一辅导啦
我们是一个针对技术岗(前后端开发、测试、测开、大数据开发)校招一对一进阶提高的工作室。我们从2020年2月份开始,迄今整整三年的时间,带领300+学员斩获1500+大厂offer,参加活动的同学人均5个中大厂offer以上,以下是我们活动内容的介绍! 万诺coding
我们主要是针对有一定基础的同学提供一对一笔试和面试辅导,针对每个同学不同的情况定制内容,包括但不限于“数据结构与算法”/“计算机基础知识”/“项目梳理”/“面试技巧”/“面试复盘”等内容。
摸底测试:如果有兴趣深入了解我们的活动,需要先参加我们的“摸底测试”(类似面试),方便我们了解你的具体情况(主要是code能力和计算机素养),定制出相应的辅导计划。同时这也是一个双向筛选的过程,如果基础过差的同学,抱歉我们可能无法辅导(基础过差的同学一对一辅导成本过高,对双方都不适合);摸底测试通过的同学,我们会定制化一个针对性的提高计划。然后你再考虑是否参加我们的活动。
承诺保offer:通过摸底测试后,我们会针对每个同学的情况给定一个“保offer”计划。然后同学可以根据自己的实际情况考虑参不参加我们的活动。
有兴趣的同学可以扫码添加我们的微信(whynotlab)