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
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);