华为2021届软件类校园招聘笔试题题解

第一题很简单,忘了是什么题了。

第二题:验证报文

难点在于进制的转换和输入输出,python对于十六进制的存储是0x__,比如5就是0x5,而C和C++就是5,这里稍有不同,当时我摸不清python版本的输入格式到底是什么,因为python只能用readline()的形式直接从命令行得到整条输入,再进行解析,这里就纠结到底是0x5还是5,想的脑子疼,(笔试结束后朋友提醒牛客网好像可以输出样例输入),就没写这道题。

题目:报文流T由报文组成,每个报文以十六进制存储,开始符是5a,结束符也是5a,在结束符之前,用一个字节来存储报文长度域(不包含开始、结束以及长度域本身),报文内如果遇到5a,5b两种字符,转义成5b ba和5b bb,但长度不变。两个报文合并时,可以将中间的5a省去一个,用一个5a同时作为上一个报文的结束符和当前报文的开始符。

例如5a 06 5b ba 37 5b bb 44 05 5a 12 34 5b ba 03 5a报文流由两个报文组成

1:5a 06 5a 37 5b 44 05 5a

2:5a 12 34 5b 03 5a

问题:现在有一个报文流,里面有部分报文是错误的,(可能是没转义,可能是长度域错误等),需要剔除错误的报文,并返回剩余正确的报文流。

思路:

一:一个十六进制占1个字节,先将输入的十六进制数据流转为整数存在数组里(考察输入)

二:遍历,将两个5a之间的数组放进子函数,子函数计算这个数组的长度(注意将转义字符看做一个字节),跟长度域比较,不相等就不管,相等就放入结果数组里,

三:将结果数组按照十六进制输出即可。(这里注意结果要补0,5要输出成05,用print('02x'%input)即可)

挺可惜,我当时被输入输出整的有点烦,也是因为LeetCode并不需要处理输入输出,所以平时练得实在不多。

 

第三题:最优子序列

题目:现有一个序列长度为m,我们要将其分解成k个子序列,1<=k<=m<=500,序列由整数组成,整数小于10^7。要求这k个子序列和的最小值尽可能大,在有多解的情况下,优先s(1)序列最大,如果s(1)相同,则s(i+1)依次往下排。

例如:

100 200 300 400 500 600 700 800 900

k=3的情况

我们需要输出: 100 200 300 400 500 / 600 700 / 800 900

这样的划分是最优的,最小值600+700=1300是能划分的最大值

思路:

这里很重要的是我们需要找出那个最优的最小值来划分序列。查找自然就要用二分查找法啦,令X为我们要找的划分值,那么我们需要用二分来找X。二分查找自然需要low和high,这里low=0无疑问,数组和最大值为500*10^7,所以high就是5e9。

那么如何判定一次二分之后mid该往哪边去呢?

试想,我们构建一个函数f,使得x能划分时,f(x)=1,不能划分时f(x)=0,那么我们需要找的X正好就是这个函数定义域的分界点,任何xX使得f(x)=0,所以mid往哪边走,由函数f返回值来确定。

接下来构建函数f。首先,我们根据x来划分序列,每个子序列必须要大于x。f(x)=0时,也就是x太大,最后划出来区域数量小于k。f(x)=1,则x存在,可以划分出k个区域(并不保证最优,但保证存在)

上代码

def make_parts(a,k,x):
    parts=[]
    num_part=0
    i=len(a)-1
    #从后往前遍历,目的是保证前面的子序列和能更大
    while i>=0:
        tmp_sum=0
        part=[]
        j=i
        #划分子区域
        while j>=0 and tmp_sum=0:
                part.append(a[i])
                i-=1
        parts.append(part)
    #x偏大,不能划分k个区域
    if num_part

子函数构建完成,外面套个二分查找即可,查找到最优值X后,再用子函数分一次X就是答案。

 

 

你可能感兴趣的:(算法,面试经历)