2021年9月29日华为机试复盘

说实话有点难受,考前一两天才想起来有个机考(怪我自己)然后刷了两天的题,自我感觉做字符串和数组的题还不错,然后说希望别考链表和IP地址之类的…………

题目是根据印象复原的,也没办法验证了,反正当时是感觉脑子一团浆糊(裂开来)

第一题 IPV6地址压缩

当时看到这题感觉我是不是可以去买彩票了,我猜中的一定不中,来跟我反着买(发家致富的道路)

IPV6格式:八段0-9,A-F。 格式错误:地址格式错误输出error; 格式正确:输出压缩后的地址 压缩规则: 1.去除开头0 2.连续两个全零保留::,八个全0::,连续两个全零后还有全零,后面的全零保留一位0。 思路: 先来一个判断IPV6地址是否正确的正则判断的函数:

	function isError(str) {
		var arr=str.split(':');
		var reg=/^[0-9A-F]{4}$/;
		// console.log(typeof arr[2],arr[2]);
		// console.log(reg.test(arr[2]));
		if(arr.length!=8){return true;}
		else{
			for(var i=0;i<arr.length;i++){
				if(!reg.test(arr[i])){
					return true;
				}
			}
			return false;
		}
	}

然后就是大块头,把完整的地址格式压缩成简写的格式: 特殊情况:“0000:0000:0000:0000:0000:0000:0000:0000”耍个赖皮直接返回两个冒号"::"。

if(str=='0000:0000:0000:0000:0000:0000:0000:0000'){
	return '::';
}

其他情况:利用正则reg=/^0{0,4}/把开头0位到4位0全部换成空字符'',此时可以得到去除先导零后的地址。以str="0000:0010:0000:0000:0010:0000:0000:0000"为例,此处可以得到arr alt

var arr=str.split(':');
var reg=/^0{0,4}/;
for(var i=0;i<arr.length;i++){
	arr[i]=arr[i].replace(reg,'');
}

然后遍历八个去除先导零后的小段,如果出现连续两个空串,则说明这两个的实际地址都是0000,此时需要先把这两个空串后面的空串都换成0。然后还需要把其中一个空串删掉,否则最后结果会多出一个冒号。 从左边起,不是连续的空串时,把空串换成0。 最后来个拼接冒号就行了。

for(var i=0;i<arr.length-1;i++){
	if(arr[i]=='' && arr[i+1]==''){
		for(var j=i+2;j<arr.length;j++){
			if(arr[j]==''){arr[j]='0';}
		}
		arr.splice(i,1);
	}else if(arr[i]==''){
		arr[i]='0';
	}
}

第二题 设备输入输出关系

这题有点小迷。

输入第一行为关系数n,输入第二行为待计算的设备devicei,输入第三行往后n行为一对设备之间的关系。

设备关系格式为:设备本身 输入设备 输出设备。 device1 device2 device3表示的设备关系链为device2->device1->device3,null表示无对应输入或输出设备。

(输入设备只能有一个,输出设备可以有多个)这个还没想好怎么解决,求指点。

	输入样例:
	4
	d1
	d1 d2 d3
	d2 null d1
	d3 d1 d4
	d4 d3 null
	上述输入表示的关系链为:d2->d1->d3->d4,求d1所在链的最大长度。

个人思路,用链表串起各个设备的关系,仅适用于输入严格符合"一个自身,一个输入,一个输出"的情况。

一长串关于链表的定义:

	//定义链表
	function dNode(s) {//节点类
		this.self=s;
		this.next=null;
	}
	function dList(){//链表类
		this.head=new dNode('head');
		this.find=find;
		this.findpre=findpre;
		this.insertq=insertq;
		this.inserth=inserth;
		this.display=display;
		this.getlength=getlength;
	}
	function find(s){//返回值为s的节点
		var currNode=this.head;
		while(currNode!=null && currNode.self!=s){
			currNode=currNode.next;
		}
		return currNode;
	}
	function findpre(s){//返回值为s的节点的前一个节点
		var currNode=this.head;
		while(currNode.next!=null && currNode.next.self!=s){
			currNode=currNode.next;
		}
		return currNode;
	}
	function insertq(newS,oldS){//把newS插入到oldS前
		var newNode=new dNode(newS);
		var currNode=this.findpre(oldS);
		newNode.next = currNode.next;
		currNode.next = newNode;
	}
	function inserth(newS,oldS){//把newS插入到oldS后
		var newNode=new dNode(newS);
		var currNode=this.find(oldS);
		newNode.next = currNode.next;
   		currNode.next = newNode;//debugger;
	}
	function display(){//展示链表
		var currNode=this.head;
		var arr=[];
		while(!(currNode.next==null)){
			arr.push(currNode.next.self);
			//console.log(currNode.next.self);
			currNode=currNode.next;
		}
		var res=arr.join('->');
		console.log(res);
	}
	function getlength(){//获取链表长度
		var num=0;
		var currNode=this.head;
		while(currNode.next!=null){
			num++;
			currNode=currNode.next;
		}
		return num;
	}

链表和相关操作定义完了之后就是怎么插入的问题了: 先遍历一遍输入的n行关系式里,找到待计算的那个设备,把这个设备本身,输入,输出的设备先插入到链表中,把这个已经插入的设备的关系从关系数组中删除。此时得到的关系链为包含待计算设备在内的一条短短的链。

	var list=new dList();
	for (var i =0;i< strArr.length ; i++) {
		var s=strArr[i].split(' ')[0];
		var sq=strArr[i].split(' ')[1];
		var sh=strArr[i].split(' ')[2];
		if(s==dai){
			list.inserth(s,'head');
			if(sq!='null'){list.insertq(sq,s);}
			if(sh!='null'){list.inserth(sh,s);}
			strArr.splice(i,1);
			break;
		}
	}

然后再在上述得到的短链中开始插入新的设备:遍历剩下的关系数组,当设备本身,该设备的输入设备,输出设备其中之一在已有关系链中找得到时,进入判断:输入设备和输出设备不为null时插入到设备前面和后面。 插入完之后把处理过的关系从关系数组里删除。

	for (var i =0;i< strArr.length ; i++) {
		var s=strArr[i].split(' ')[0];
		var sq=strArr[i].split(' ')[1];
		var sh=strArr[i].split(' ')[2];
		if(list.find(s)!=null||list.find(sq)!=null||list.find(sh)!=null){
			if(sq!='null'&&list.find(sq)==null){list.insertq(sq,s);}
			if(sh!='null'&&list.find(sh)==null){list.inserth(sh,s);}
			strArr.splice(i,1);
		}
		i--;
	}
	list.display();
	console.log(list.getlength());

第三题 求所有子区间的面积和

要求:输入字符串,以空格隔开,输出这组字符串的所有子区间的面积和。

面积定义为区间内(最大值-最小值)*(区间长度)

	例:
	100 10 1000
	三个子区间:
	100 10 		面积:(100-10)*2
	10 1000 	面积:(1000-10)*3
	100 1000	面积:(1000-100)*2

这题本身不难,就是题目要求运行时间限制2秒,我用的两重循环,时间超限了。求助怎么在时间限制内完成?应该是有不用二重循环的解法po。

	var str="30 20 10 5 3 1";
	var arr=str.split(' ');
	arr.sort(function(a,b) {
		return parseInt(a)-parseInt(b);
	})
	var s=0;
	var res=0;
	for (var i=0;i<arr.length-1;i++) {
		for (var j=i+1;j<arr.length;j++){
			var x=parseInt(arr[i]);
			var y=parseInt(arr[j]);
			s=(y-x)*(j-i+1);
			res+=s;
		}
	}
	console.log(res);
全部评论
请问第二题和第三题有思路了吗?
点赞 回复 分享
发布于 2021-10-07 14:19
# 第三题: python3.5+ from typing import List def sub_interval_area(arr: List[int]): """ arr, 递增的数组(非严格) :return: 子区间面积和 """ # 根据推证(如图), 需要有顺序(ai<=aj if i
点赞 回复 分享
发布于 2021-10-29 14:15
发不了图片居然。。。
点赞 回复 分享
发布于 2021-10-29 14:16
第三题,区间长度公式可以推到为:(n+2)sum{a_i*i} - (n+2)*(n-1)/2*sum{a_i},复杂度为O(n)
点赞 回复 分享
发布于 2021-10-29 14:24

相关推荐

ArisRobert:统一解释一下,第4点的意思是,公司按需通知员工,没被通知到的员工是没法去上班的,所以只要没被通知到,就自动离职。就是一种比较抽象的裁员。
点赞 评论 收藏
分享
沉淀一会:**圣经 1.同学你面试评价不错,概率很大,请耐心等待;2.你的排名比较靠前,不要担心,耐心等待;3.问题不大,正在审批,不要着急签其他公司,等等我们!4.预计9月中下旬,安心过节;5.下周会有结果,请耐心等待下;6.可能国庆节前后,一有结果我马上通知你;7.预计10月中旬,再坚持一下;8.正在走流程,就这两天了;9.同学,结果我也不知道,你如果查到了也告诉我一声;10.同学你出线不明朗,建议签其他公司保底!11.同学你找了哪些公司,我也在找工作。
点赞 评论 收藏
分享
评论
3
12
分享
牛客网
牛客企业服务