机考[1-10]

1年前 (2023) 程序员胖胖胖虎阿
102 0 0

华为机考

    • 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;
    }
}

版权声明:程序员胖胖胖虎阿 发表于 2023年9月4日 上午3:24。
转载请注明:机考[1-10] | 胖虎的工具箱-编程导航

相关文章

暂无评论

暂无评论...