最近有机会尝试做了一下华为机试题,感觉整个过程还是挺有意思的,分享一下经历。

前面说一下体验和注意点,后面附上题目和解题思路,本文使用python解题

一、体验和一些注意点

1、总体的感觉:

难度比预想的小挺多,练习题有些很难的,涉及算法啥的,实际没有考到。做是能做出来的,最后一道题测试用例有些没通过,应该是场景考虑不够全面。

2、题型:

考试时长150分钟。三道应用编程题,生活中的问题,用程序解决。
前两道各100分,第三道200分。
前两道相对简单点,第三道可能会涉及到比较难的算法。可以自由选择编程语言,例如C,C++,Java,Python等,没有sql。

3、计分逻辑(个人猜测):

考完后思考了一下,分数的计算逻辑应该是按照测试用例的通过比例来算的,例如:最后一道题总分200分,测试用例通过率50%, 那么你的得分就是100分。

4、规则:

邮件发送考试链接和规则,附有练习地址,7天内考完即可,错过了半年内无法再考,作弊则以后没机会参与华为项目。
可以在浏览器上编辑调试测试代码,也可以在本地IDE写好粘贴上去,但不允许使用现有代码。
需要自己处理输入输出,可能会涉及多行输入输出问题,还可能给你个数组格式的字符串,需要自己处理成真正的数组,比较麻烦的可能是多行输入的同时还有矩阵,不过考试时有提供处理的案例,不用担心。

5、监控规则:

考试前打开摄像头,开启浏览器录屏监控,扫码打开小程序监控手机,手机屏幕必须全程亮着,停留在小程序界面,息屏或者跳出小程序三次则结束考试。允许使用纸笔,允许中途离开摄像头,最好2分钟内回来。

6、考前练习:

牛客网有华为机试练习,有107道题左右,有简单的也有难的,难的一般是算法题,会限制时间复杂度和空间复杂度,有可能因为占用内存过多或者运行时间超长而无法通过

7、考试时感觉比较坑的地方:
7.1、测试详情看不到:

考前的练习有提供测试用例的预期结果和实际结果对比,不通过的话对比结果也比较容易找到问题在哪。实际考试虽然也有提供测试用例,但你无法知道测试用例是怎样的,也不知道哪些没通过,要是遇到判断场景比较多的,考虑少了就只能自己摸瞎找问题了,最好练一下如何批量生成测试用例。

7.2、测试提供的场景太简单

考试时是有提供一两个测试例子用来示范输入和输出结果的,但是很普通,你需要自己去考虑特殊的场景。
就好比如让你计算考勤情况判断该员工能不能拿全勤奖,有多个要求,其中一个要求是不能出来连续的迟到/早退,结果我脑补的场景是今天迟到并且明天早退,或者今天早退并且明天迟到则无法拿全勤奖,然后部分测试用例没通过。由于看不到测试详情,就只能摸瞎一个个条件重新考虑,最终发现是这个要求下面有两个场景没考虑到: 连续两天都迟到或者连续两天早退也是不能拿全勤奖的。

二、接下来说一下遇到的题目

1、第一道题比较简单:字符串的去重和排序

题目:两次输入,各输入一行小写字母构成的字符串,要求从第一次输入的字符串中找出第二行字符串中有的,按照ascii编码排序, 最终输出没有重复字母的字符串。

示例:
输入:
bacha
bbaaccedfg

输出:
abc

解法1:
利用集合去重,取交集,再转列表,排序,拼接

print(''.join(sorted(list(set(input()) & set(input())))))

解法2:
几乎就是字符串的基本操作,没啥好说的

s = input()
s2 = input()
s1 = ''

for i in s:
    if s2.count(i) > 0:
        if i in s1:
            pass
        else:
            s1 += i

s1 = ''.join(sorted(s1))
print(s1)
2、第二题稍微增加了难度:考勤问题,考的主要是字符串的操作和逻辑判断

一公司使用字符串来记录考勤,首行输入的数字代表接下来需要判断的员工数,后面每一行代表一个员工的出勤记录,每行不超过10000个字符,每个单词代表每天的出勤情况,
present代表正常出勤,absent代表缺席,late代表迟到,leaveearly代表早退,单词之间用空格隔开。
如下所示:
present
present present

现需要判断每个员工是否能获得全勤奖, 获得全勤奖的规则是:缺勤不超过1次,没有连续的迟到/早退,
任意连续7天内出现缺勤/迟到/早退的次数不超过3次。

输出要求:结果输出为一行,以空格隔开

示例1:
输入:
2
present
present present

输出:
true true

示例2:
输入:
3
present
absent present late present present present present leaveearly late present present

输出:
true true false

解法1:
利用字符串替换为数字,通过统计数字之和,判断。较为灵活


def rule_1(s):
    '''缺勤不超过1次,没有连续的迟到早退'''
    if s.count('absent') > 1:
        return False
    # 把迟到,早退替换为0,其他都替换为1,逐一取2个判断和是否为0
    li = s.split(' ')
    li = list(map(lambda x: 0 if x=='late' or x=='leaveearly' else 1, li))
    for i in range(len(li)-1):
        if sum(li[i:i+2]) == 0:
            return False
    return True


def rule_2(s):
    '''任意连续7天内出现缺勤/迟到/早退的次数不超过3次'''
    # 把缺勤/迟到/早退赋值为1,其他赋值为0,逐一取7个,和大于3则返回Fasle
    li = s.split(' ')
    li = list(map(lambda x: 1 if x == 'absent' or x == 'late' or x == 'leaveearly' else 0, li))
    for i in range(len(li) - 6):
        print(li[i:i + 7])
        if sum(li[i:i + 7]) > 3:
            return False
    return True

if __name__ == '__main__':
    import sys

    n = sys.stdin.readline().strip()

    ret = []
    for i in range(int(n)):
        line = sys.stdin.readline().strip()
        if rule_1(line) and rule_2(line):
            ret.append('true')
        else:
            ret.append('false')

    print(' '.join(ret))

解法二:
比较呆板的统计,直接统计字符串

# 自己编的测试用例三,相比官方给的2个简单测试用例,覆盖场景较多
s1 = 'present'
s2 = 'absent present late present present present present leaveearly late present present'
s3 = 'absent present late present present present present leaveearly present present'
s4 = 'absent present late present present present present late leaveearly present present'
s5 = 'absent present present present late present present leaveearly present present present late present present'
s6 = 'absent present present present present present present present present late late'
# s = ''
def can_award(s1):
    l = s1.split(' ')
    if s1.count('absent') > 1:
        # 缺勤大于1
        return 'false'
    if s1.count('late leaveearly') > 0 or s1.count('leaveearly late') >0 \
            or s1.count('late late') >0 or s1.count('leaveearly leaveearly')> 0:
        # 有连续的迟到/早退
        return 'false'
    for i in range(len(l)):
        # 当查到有缺勤或者迟到或者早退时,获取往后的6个记录,检查是否有迟到早退
        this = l[i]
        if this == 'absent' or this == 'late' or this == 'leaveearly':
            c = 0
            l1 = l[i+1: i+7]
            print(l1)
            c += l1.count('absent')
            c += l1.count('late')
            c += l1.count('leaveearly')
            print(c)
            if c > 2:
                return 'false'
    return 'true'

import sys

# 读取第一行的n
n = int(sys.stdin.readline().strip())
l = []
for i in range(n):
    # 读取每一行
    line = sys.stdin.readline().strip()
    print(line)
    l.append(can_award(line))
print(' '.join(l))
3、第三题:书本叠放问题

题目:假设书本的叠放有这样的规则,当A书的长度和宽度都大于B书时,可以将其B书置于A的上方,堆叠摆放,请设计一个程序,根据输入的书本长宽,计算最多可以堆叠摆放多少本书?

示例:这里代表有3本书,第1本长宽分别为16和15,第2本长宽为13和12,第3本长宽为15和14。
输入:
[[16,15], [13, 12], [15, 14]]

输出:
3

解题思路:
1、先处理好输入的字符串,转成python的列表
2、列表内嵌列表,可以考虑转成字典并按键排好序,方便快速比较

# 官方给的测试用例
# s = '[[16,15], [13, 12], [15, 14]]'
# 自己写的测试用例
s = '[[16,15], [16, 14], [13, 12], [15, 14]]'
# s = input()
s = s.replace(' ', '')
s = s.replace('],[', '];[')
l = s[1:-1].split(';')
# print(l)
d = {}
for i in l:
    # 如果该键已存在d中,需要比对值的大小,取大的
    if i[1:-1].split(',')[0] in d.keys():
        d[i[1:-1].split(',')[0]] = int(i[1:-1].split(',')[1]) if int(i[1:-1].split(',')[1]) >= d[i[1:-1].split(',')[0]] \
            else d[i[1:-1].split(',')[0]]
    else:
        d[i[1:-1].split(',')[0]] = int(i[1:-1].split(',')[1])

# print(d)
d2 = {}
for j in sorted(d, reverse=True):  # 按键从大到小排序
    d2[j] = d[j]

keys = list(d2.keys())   # 排完续后的键值对
# print(keys)
c = 0
for k,v in d2.items():
    k_index = keys.index(k)
    for i in keys[k_index+1::]:
        if v > d2[i]:
            c += 1
print(c)

第三题考的时候没有完全通过所有测试用例,考完改进了一下,这里上的是改后的代码,目前没测出什么问题,有兴趣的朋友可以多写几个测试用例测一下,有发现不对的结果可以私信我说一下。

一开始以为会有些很难的算法,所以这几天一直在看算法,做的时候发现还好没遇到,考得过可能跟运气也有关。

另外,好的测试很重要,如果测试用例覆盖场景足够多,可以更快地找出程序的问题在哪。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐