华为机考
-
- 001 【5键键盘的输出】
- 002 【N进制减法】
- 003 【TLV解码】
- 004 【VLAN资源池】
- 005 【按身高和体重排队】
- 006 【按索引范围翻转文章片段】
- 007 【报数游戏】
- 008 【比赛评分】
- 009 【查找接口成功率最优时间段】
001 【5键键盘的输出】
有一个特殊的5键键盘,上面有a,ctrl-c,ctrl-x,ctrl-v,ctrl-a五个键。a键在屏幕上输出一个字母a;ctrl-c将当前选择的字母复制到剪贴板;ctrl-x将当前选择的字母复制到剪贴板,并清空选择的字母;ctrl-v将当前剪贴板里的字母输出到屏幕;ctrl-a选择当前屏幕上的所有字母。注意:
1剪贴板初始为空,新的内容被复制到剪贴板时会覆盖原来的内容
2当屏幕上没有字母时,ctrl-a无效
3当没有选择字母时,ctrl-c和ctrl-x无效
4当有字母被选择时,a和ctrl-v这两个有输出功能的键会先清空选择的字母,再进行输出
给定一系列键盘输入,输出最终屏幕上字母的数量。
输入描述:
输入为一行,为简化解析,用数字1 2 3 4 5代表a,ctrl-c,ctrl-x,ctrl-v,ctrl-a五个键的输入,数字用空格分隔 输出描述:
输出一个数字,为最终屏幕上字母的数量
示例1:
输入 1 1 1
输出 3
说明 连续键入3个a,故屏幕上字母的长度为3
示例2:
输入 1 1 5 1 5 2 4 4
输出 2
说明 输入两个a后ctrl-a选择这两个a,再输入a时选择的两个a先被清空,所以此时屏幕只有一个a,后续的ctrl-a,ctrl-c选择并复制了这一个a,最后两个ctrl-v在屏幕上输出两个a,故屏幕上字母的长度为2(第一个ctrl-v清空了屏幕上的那个a)
public class ZT01 {
private static String screen = "";
private static String choose = "";
private static String jianQie = "";
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] input = sc.nextLine().split(" ");
for (int i = 0; i < input.length; i++) {
operate(Integer.parseInt(input[i]));
}
System.out.println(screen.length());
}//a
public static void operate(int num){
if (num == 1){//a screen输入一个a
if (choose.equals("")){
screen += "a";
}else {
choose = "";
screen = "a";
}
return;
}
if (num == 2){//ctrl-c
jianQie = choose;
return;
}
if (num == 3){//ctrl-x
jianQie = choose;
choose = "";
screen = "";
return;
}
if (num ==4){//ctrl-v
if (choose.equals("")){
screen += jianQie;
}else {
screen = jianQie;
choose = "";
}
return;
}
if (num == 5){//ctrl-a
choose = screen;
}
}
}
002 【N进制减法】
实现一个基于字符串的N机制的减法。
需要对输入的两个字符串按照给定的N进制进行减法操作,输出正负符号和表示结果的字符串。
输入描述:
输入:三个参数。
第一个参数是整数形式的进制N值,N值范围为大于等于2、小于等于35。
第二个参数为被减数字符串;
第三个参数为减数字符串。有效的字符包括09以及小写字母az,字符串有效字符个数最大为100个字符,另外还有结尾的\0。
限制:
输入的被减数和减数,除了单独的0以外,不能是以0开头的字符串。
如果输入有异常或计算过程中有异常,此时应当输出-1表示错误。
输出描述:
输出:2个。
其一为减法计算的结果,-1表示出错,0表示结果为整数,1表示结果为负数。
其二为表示结果的字符串。
示例1:
输入
2 11 1
输出
0 10
说明
按二进制计算 11 -1 ,计算正常,0表示符号为正数,结果为10
示例2:
输入
8 07 1
输出
-1
说明
按8进制,检查到减数不符合非0前导的要求,返回结果为-1,没有其他结果内容。
public class ZT02 {//2 11 1
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] input = sc.nextLine().split(" ");
int jin = Integer.parseInt(input[0]);
String numStr = input[1];
String jianStr = input[2];
//检查开头
if (numStr.length() != 1 && jianStr.length() != 1 && (numStr.startsWith("0") || jianStr.startsWith("0"))){
System.out.println(-1);
return;
}
//检查结尾
if (numStr.endsWith("/0")){
numStr = numStr.substring(0,numStr.length()-2);
}
if (jianStr.endsWith("/0")){
jianStr = jianStr.substring(0,jianStr.length()-2);
}
int no1 = 0;
int no2 = 0;
try {
no1 = Integer.parseInt(numStr, jin);
no2 = Integer.parseInt(jianStr, jin);
}catch (Exception e){
System.out.println(-1);
return;
}
int res = no1 - no2;
if (no1 - no2 > 0){
System.out.print(0+" ");
}else {
System.out.print(1+" ");
}
System.out.println(Integer.toString(res, jin));
}
}
003 【TLV解码】
TLV编码是按[Tag Length Value]格式进行编码的,一段码流中的信元用Tag标识,Tag在码流中唯一不重复,Length表示信元Value的长度,Value表示信元的值。
码流以某信元的Tag开头,Tag固定占一个字节,Length固定占两个字节,字节序为小端序。
现给定TLV格式编码的码流,以及需要解码的信元Tag,请输出该信元的Value。
输入码流的16机制字符中,不包括小写字母,且要求输出的16进制字符串中也不要包含小写字母;码流字符串的最大长度不超过50000个字节。
输入描述:
输入的第一行为一个字符串,表示待解码信元的Tag;
输入的第二行为一个字符串,表示待解码的16进制码流,字节之间用空格分隔。
输出描述:
输出一个字符串,表示待解码信元以16进制表示的Value。
示例1:
输入
31
32 01 00 AE 90 02 00 01 02 30 03 00 AB 32 31 31 02 00 32 33 33 01 00 CC
输出
32 33
说明
需要解析的信元的Tag是31,从码流的起始处开始匹配,Tag为32的信元长度为1(01 00,小端序表示为1);第二个信元的Tag是90,其长度为2;第三个信元的Tag是30,其长度为3;第四个信元的Tag是31,其长度为2(02 00),所以返回长度后面的两个字节即可,即32 33。
/**
* TLV解码
* tag 一个字节 //第一行
* length占2个字节
* 字节为小端序
* 1各字节占8位 length 16位
* 1个16进制数 占2进制多少位? 4位 所以length 占4个数
* * //32 00 01 AE
* //90 00 02 01 02
* //30 00 03 AB 32 31
* //31 00 02 32 33
* //33 0 01 CC
* */
public class ZT03 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String tag = sc.nextLine();//需要解析的tag
String stream = sc.nextLine();//所有的tag内容
Map<String,Inner> map = new HashMap<>();
//分割所有码流数据,塞到map中
String[] input = stream.split(" ");
int idx = 0;
while (idx < input.length){
String tagTemp = input[idx];
String lengthStr = input[idx+2] + input[idx+1];
idx += 3;
//计算内容的长度
int length = Integer.parseInt(lengthStr,16);
StringBuilder content = new StringBuilder();
for (int i = idx; i < idx + length; i++) {
if (i == idx+length -1){
content.append(input[i]);
}else {
content.append(input[i]).append(" ");
}
}
map.put(tagTemp,new Inner(length,content.toString()));
idx += length;
}
Inner inner = map.get(tag);
System.out.println(inner.content);
}
static class Inner{
private int length;
private String content;
public Inner(int length, String content) {
this.length = length;
this.content = content;
}
}
}
004 【VLAN资源池】
VLAN是一种对局域网设备进行逻辑划分的技术,为了标识不同的VLAN,引入VLAN ID(1-4094之间的整数)的概念。定义一个VLAN ID的资源池(下称VLAN资源池),资源池中连续的VLAN用开始VLAN-结束VLAN表示,不连续的用单个整数表示,所有的VLAN用英文逗号连接起来。现在有一个VLAN资源池,业务需要从资源池中申请一个VLAN,需要你输出从VLAN资源池中移除申请的VLAN后的资源池。
输入描述:
第一行为字符串格式的VLAN资源池,第二行为业务要申请的VLAN,VLAN的取值范围为[1,4094]之间的整数。
输出描述:
从输入VLAN资源池中移除申请的VLAN后字符串格式的VLAN资源池,输出要求满足题目描述中的格式,并且按照VLAN从小到大升序输出。
如果申请的VLAN不在原VLAN资源池内,输出原VLAN资源池升序排序后的字符串即可。
示例1:
输入
1-5
2
输出
1,3-5
说明
原VLAN资源池中有VLAN 1、2、3、4、5,从资源池中移除2后,剩下VLAN 1、3、4、5,按照题目描述格式并升序后的结果为1,3-5。
示例2:
输入
20-21,15,18,30,5-10
15
输出
5-10,18,20-21,30
说明
原VLAN资源池中有VLAN 5、6、7、8、9、10、15、18、20、21、30,从资源池中移除15后,资源池中剩下的VLAN为 5、6、7、8、9、10、18、20、21、30,按照题目描述格式并升序后的结果为5-10,18,20-21,30。
示例3:
输入
5,1-3
10
输出
1-3,5
说明
原VLAN资源池中有VLAN 1、2、3,5,申请的VLAN 10不在原资源池中,将原资源池按照题目描述格式并按升序排序后输出的结果为1-3,5。
备注:
输入VLAN资源池中VLAN的数量取值范围为[2-4094]间的整数,资源池中VLAN不重复且合法([1,4094]之间的整数),输入是乱序的。
public class ZT04 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] input = sc.nextLine().split(",");
int search = sc.nextInt();
List<Integer> list = new ArrayList<>();
for (int i = 0; i < input.length; i++) {
if (input[i].contains("-")){
String[] num = input[i].split("-");
int start = Integer.parseInt(num[0]);
int end = Integer.parseInt(num[1]);
for (int j = start; j <end+1 ; j++) {
list.add(j);
}
}else {
list.add(Integer.parseInt(input[i]));
}
}
Collections.sort(list);
list.remove((Object) search);
//输出
int idx = 0;
int start = 0;//1 3 4 5
int tem = 1;
StringBuffer sb = new StringBuffer();
while (idx < list.size()){
if (start == 0){
start = list.get(idx);
}
if (idx+1 == list.size()){//保证下一位一定存在
sb.append(start);
break;
}
if (list.get(idx+1) == start+tem){//下一位与当前相等 继续后推
idx ++;
tem ++;
continue;
}else if (start == list.get(idx)){//输出当前值加,
sb.append(start).append(",");
start = 0;
tem = 1;
}else {
sb.append(start).append("-").append(list.get(idx));
start = 0;
tem = 1;
if (idx +1 < list.size()){//当前不是最后一个数据
sb.append(",");
}
}
idx ++;
}
System.out.println(sb);
}
}
005 【按身高和体重排队】
某学校举行运动会,学生们按编号(1、2、3…n)进行标识,现需要按照身高由低到高排列,对身高相同的人,按体重由轻到重排列;对于身高体重都相同的人,维持原有的编号顺序关系。请输出排列后的学生编号。
输入描述:
两个序列,每个序列由n个正整数组成(0 < n <= 100)。第一个序列中的数值代表身高,第二个序列中的数值代表体重。
输出描述:
排列结果,每个数值都是原始序列中的学生编号,编号从1开始
示例1:
输入
4
100 100 120 130
40 30 60 50
输出
2 1 3 4
说明
输出的第一个数字2表示此人原始编号为2,即身高为100,体重为30的这个人。由于他和编号为1的人身高一样,但体重更轻,因此要排在1前面。
示例2:
输入
3
90 110 90
45 60 45
输出
1 3 2
说明
1和3的身高体重都相同,需要按照原有位置关系让1排在3前面,而不是3 1 2
public class ZT05 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int count = Integer.parseInt(sc.nextLine());
String[] high = sc.nextLine().split(" ");
String[] weight = sc.nextLine().split(" ");
List<Player> playerList = new ArrayList<>();
for (int i = 0; i < count; i++) {
playerList.add(new Player(i+1,Integer.parseInt(high[i]),Integer.parseInt(weight[i])));
}
Collections.sort(playerList);
for (int i = 0; i < playerList.size(); i++) {
System.out.print(playerList.get(i).idx+" ");
}
}
static class Player implements Comparable<Player>{
private int idx;
private int high;
private int weight;
public Player(int idx, int high, int weight) {
this.idx = idx;
this.high = high;
this.weight = weight;
}
@Override
public int compareTo(Player ply) {
if (ply.high > this.high){
return -1;
}
if (ply.weight > this.weight){
return -1;
}
if (ply.idx > this.idx){
return -1;
}
return 0;
}
}
}
006 【按索引范围翻转文章片段】
输入一个英文文章片段,翻转指定区间的单词顺序,标点符号和普通字母一样处理。例如输入字符串"I am a developer. “,区间[0,3],则输出"developer. a am I"
String reverseWords(String s, int start, int end)
输入描述:
使用换行隔开三个参数,第一个参数为英文文章内容即英文字符串,第二个参数为翻转起始单词下标(下标从0开始),第三个参数为结束单词下标。
输出描述:
翻转后的英文文章片段所有单词之间以一个半角空格分隔进行输出
示例1:
输入
I am a developer.
1
2
输出
I a am developer.
示例2:
输入
hello world!
0
1
输出
world! hello
说明
输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。
示例3:
输入
I am a developer.
0
3
输出
developer. a am I
说明
如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。
示例4:
输入
Hello!
0
3
输出
EMPTY
说明
指定翻转区间只有一个单词或无有效单词,则统一输出"EMPTY"
public class ZT06 {
private static String[] content;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String input = sc.nextLine();
String[] num = sc.nextLine().split(" ");
System.out.println(reverseWords(input, Integer.parseInt(num[0]), Integer.parseInt(num[1])));
}
private static String reverseWords(String str,int start,int end){
String[] content = str.split(" ");
while (start < end){
String temp = "";
temp = content[end];
content[end] = content[start];
content[start] = temp;
start++;
end--;
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < content.length; i++) {
sb.append(content[i]);
if (i+1 < content.length){
sb.append(" ");
}
}
return sb.toString();
}
}
007 【报数游戏】
100个人围成一圈,每个人有一个编码,编号从1开始到100。他们从1开始依次报数,报到为M的人自动退出圈圈,然后下一个人接着从1开始报数,直到剩余的人数小于M。请问最后剩余的人在原先的编号为多少?
输入描述:
输入一个整数参数M
输出描述:
如果输入参数M小于等于1或者大于等于100,输出“ERROR!”;否则按照原先的编号从小到大的顺序,以英文逗号分割输出编号字符串
示例1:
输入
3
输出
58,91
说明
输入M为3,最后剩下两个人
示例2:
输入
4
输出
34,45,97
说明
输入M为4,最后剩下三个人
public class ZT07 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int num = sc.nextInt();
if (num <= 1 || num>= 100){
System.out.println("ERROR!");
return;
}
Map<Integer,Integer> map = new HashMap<>();
for (int i = 1; i < 101; i++) {
map.put(i,i);
}
int start = 1 ;
while (map.size() >= num){
Iterator<Map.Entry<Integer, Integer>> iterator = map.entrySet().iterator();
while (iterator.hasNext()){
Map.Entry<Integer, Integer> next = iterator.next();
Integer key = next.getKey();
map.put(key,start++);
Integer value = next.getValue();
if (value == num){
iterator.remove();
start = 1;
}
}
}
StringBuilder sb = new StringBuilder();
for (Map.Entry<Integer, Integer> cou : map.entrySet()) {
sb.append(cou.getKey()).append(",");
}
sb.deleteCharAt(sb.lastIndexOf(","));
System.out.println(sb);
}
}
008 【比赛评分】
一个有N个选手参加比赛,选手编号为1~N(3<=N<=100),有M(3<=M<=10)个评委对选手进行打分。打分规则为每个评委对选手打分,最高分10分,最低分1分。
请计算得分最多的3位选手的编号。如果得分相同,则得分高分值最多的选手排名靠前(10分数量相同,则比较9分的数量,以此类推,用例中不会出现多个选手得分完全相同的情况)。
输入描述:
第一行为半角逗号分割的两个正整数,第一个数字表示M(3<=M<=10)个评委,第二个数字表示N(3<=N<=100)个选手。
第2到M+1行是半角逗号分割的整数序列,表示评委为每个选手的打分,0号下标数字表示1号选手分数,1号下标数字表示2号选手分数,依次类推。
输出描述:
选手前3名的编号。
注:若输入为异常,输出-1,如M、N、打分不在范围内。
示例1:
输入
4,5
10,6,9,7,6
9,10,6,7,5
8,10,6,5,10
9,10,8,4,9
输出
2,1,5
说明
第一行代表有4个评委,5个选手参加比赛
矩阵代表是4*5,每个数字是选手的编号,每一行代表一个评委对选手的打分排序,
2号选手得分36分排第1,1号选手36分排第2,5号选手30分(2号10分值有3个,1号10分值只有1个,所以2号排第一)
示例2:
输入
2,5
7,3,5,4,2
8,5,4,4,3
输出
-1
说明:只有2个评委,要求最少为3个评委
示例3:
输入
4,2
8,5
5,6
10,4
8,9
输出
-1
说明:只有2名选手参加,要求最少为3名
示例4:
输入
4,5
11,6,9,7,8
9,10,6,7,8
8,10,6,9,7
9,10,8,6,7
输出
-1
说明:第一个评委给第一个选手打分11,无效分数
public class ZT08 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] num = sc.nextLine().split(",");
int ma = Integer.parseInt(num[0]);//教练
int no = Integer.parseInt(num[1]);//选手
if (ma>10 || ma<3 || no>100 || no<3){
System.out.println(-1);
return;
}
List<String[]> list = new ArrayList<>();
for (int i = 0; i < ma; i++) {
list.add(sc.nextLine().split(","));
}
//收集选手信息
List<Player> players = new ArrayList<>();
for (int i = 0; i < no; i++) {//第i个选手
int total = 0;
List<Integer> listScore = new ArrayList<>();
for (int j = 0; j < ma; j++) {//第j个裁判
String[] strings = list.get(j);
int score = Integer.parseInt(strings[i]);
if (score<0 || score>10){
System.out.println(-1);
return;
}
listScore.add(score);
total+= score;
}
players.add(new Player(i,total,listScore));
}
//比较选手分数
Collections.sort(players);
for (int i = 0; i < 3; i++) {
if (i == 2){
System.out.println(players.get(i).idx+1);
}else {
System.out.print(players.get(i).idx+1 + ",");
}
}
}
static class Player implements Comparable<Player>{
private int idx;
private int total;
private List<Integer> scores;
public Player(int idx,int total, List<Integer> scores) {
this.idx = idx;
this.total = total;
this.scores = scores;
}
private int checkCount(List<Integer> list,int count){
int cou = 0;
for (int i = 0; i < list.size(); i++) {
if (list.get(i) == count) {
cou++;
}
}
return cou;
}
@Override
public int compareTo(Player ply) {
//先比较总分
if (ply.total < this.total){
return -1;
}else if (ply.total > this.total){
return 1;
}else {
//后比较最高分的数量
List<Integer> scPly = ply.scores;
List<Integer> scores = this.scores;
for (int i = 10; i > 0; i--) {
int ipl = checkCount(scPly, i);
int ith = checkCount(scores, i);
if (ipl < ith){
return -1;
}
}
}
return 0;
}
}
}
009 【查找接口成功率最优时间段】
服务之间交换的接口成功率作为服务调用关键质量特性,某个时间段内的接口失败率使用一个数组表示,数组中每个元素都是单位时间内失败率数值,数组中的数值为0~100的整数,给定一个数值(minAverageLost)表示某个时间段内平均失败率容忍值,即平均失败率小于等于minAverageLost,找出数组中最长时间段,如果未找到则直接返回NULL。
输入描述:
输入有两行内容,第一行为{minAverageLost},第二行为{数组},数组元素通过空格(" “)分隔,minAverageLost及数组中元素取值范围为0~100的整数,数组元素的个数不会超过100个。
输出描述:
找出平均值小于等于minAverageLost的最长时间段,输出数组下标对,格式{beginIndex}-{endIndx}(下标从0开始),如果同时存在多个最长时间段,则输出多个下标对且下标对之间使用空格(” ")拼接,多个下标对按下标从小到大排序。
示例1:
输入
1
0 1 2 3 4
输出
0-2
说明
A、输入解释:minAverageLost=1,数组[0, 1, 2, 3, 4]
B、前3个元素的平均值为1,因此数组第一个至第三个数组下标,即0-2
示例2:
输入
2
0 0 100 2 2 99 0 2
输出
0-1 3-4 6-7
说明
A、输入解释:minAverageLost=2,数组[0, 0, 100, 2, 2, 99, 0, 2]
B、通过计算小于等于2的最长时间段为:数组下标为0-1即[0, 0],数组下标为3-4即[2, 2],数组下标为6-7即[0, 2],这三个部分都满足平均值小于等2的要求,因此输出0-1 3-4 6-7
public class ZT09 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int num = Integer.parseInt(sc.nextLine());
String[] arr0 = sc.nextLine().split(" ");
int[] arr = new int[arr0.length];
for (int i = 0; i < arr0.length; i++) {
arr[i] = Integer.parseInt(arr0[i]);
}
int left = 0;
int right = 0;
StringBuilder sb = new StringBuilder();
while (right < arr.length){
if (left == right){
right++;
}
if (checkAvMin(arr,left,right,num)){//需要查找到最大的数组?
while (right <arr.length && checkAvMin(arr,left,right,num)){
right++;
}
right--;
sb.append(left).append("-").append(right).append(" ");
right++;
}else {
left++;
}
}
System.out.println(sb);
}
//给出数组,求平均值是否小于等于某个期望值
private static boolean checkAvMin(int[] arr,int start,int end,int target){
double total = 0;
for (int i = start; i < end+1; i++) {
total += arr[i];
}
double res = total/(end - start +1);
return res <= target;
}
}