我是靠谱客的博主 高兴万宝路,最近开发中收集的这篇文章主要介绍华为od机试题5 真题,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

华为od机试题 真题

    • 45.满足规则的数组组合
    • 44.最长连续子序列的和等于输入值
    • 43.整数编码
    • 42.输出指定格式字符
    • 40.小朋友分班
    • 39.数列解析
    • 38. url拼接
    • 36.满足最低能力值的数量

以下题目附带Java解法,是我个人写的,不一定是标准答案,没有真正的测试数据,只能说是我自己认为通过率100%,也不一定是最优解。如果有错误或是有更好的解法,请评论告诉我!!!

45.满足规则的数组组合

 给定一个正整数数组
 检查数组中是否存在满足规则的数组组合
 规则:
 A=B+2C
 输入描述
 第一行输出数组的元素个数
 接下来一行输出所有数组元素  用空格隔开
 输出描述
 如果存在满足要求的数
 在同一行里依次输出 规则里 A/B/C的取值 用空格隔开
 如果不存在输出0

 示例1:
 输入
 4
 2 7 3 0
 输出
 7 3 2
 说明:
 7=3+2*2
 示例2:
 输入
 3
 1 1 1
 输出
 0
 说明找不到满足条件的组合

 备注:
 数组长度在3~100之间
 数组成员为0~65535
 数组成员可以重复
 但每个成员只能在结果算式中使用一次
 如 数组成员为 [0,0,1,5]
 0出现两次允许,但结果0=0+2*0不允许  因为算式中使用了3个0

 用例保证每组数字里最多只有一组符合要求的解
    // 满足规则的数组组合
    // 解题思路:对输入的数字进行排序,a从后往前取,取最大的,b、c取比a小的,且b!=c
    public static void test045(){
        Scanner sc = new Scanner(System.in);
        int len = Integer.parseInt(sc.nextLine());
        String line = sc.nextLine();
        String[] split = line.split(" ");
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < len; i++) {
            list.add(Integer.parseInt(split[i]));
        }
        // 对list进行排序
        Collections.sort(list);
        // 三重循环,虽然效率低,但是简单
        for (int a = len - 1; a >= 0; a--) {
            // A的值肯定是大于等于B、C的,所以B、C的取值范围要在a前
            for (int b = 0; b < a; b++) {
                // c!=b 是因为每个成员只能在结果算式中使用一次
                for (int c = 0; c < a && c != b; c++) {
                    if (list.get(a) == list.get(b) + 2*list.get(c)) {
                        System.out.println(list.get(a) + " " + list.get(b) + " " + list.get(c));
                        return;
                    }
                }
            }
        }
        System.out.println(0);
    }

44.最长连续子序列的和等于输入值

 有N个正整数组成的一个序列
 给定一个整数sum
 求长度最长的的连续子序列使他们的和等于sum
 返回次子序列的长度
 如果没有满足要求的序列 返回-1
 案例1:
 输入
 1,2,3,4,2
 6
 输出
 3
 解析:1,2,3和4,2两个序列均能满足要求
 所以最长的连续序列为1,2,3 因此结果为3

 示例2:
 输入
 1,2,3,4,2
 20
 输出
 -1
 解释:没有满足要求的子序列,返回-1

 备注: 输入序列仅由数字和英文逗号构成
 数字之间采用英文逗号分割
 序列长度   1<=N<=200
 输入序列不考虑异常情况
 由题目保证输入序列满足要求
    // 最长连续子序列的和等于输入值
    // 解题思路:双层循环,第一层遍历每一个数字,第二层往后累加,记录符合条件的长度,保留最大长度
    public static void test044(){
        Scanner sc = new Scanner(System.in);
        String line = sc.nextLine();
        int num = Integer.parseInt(sc.nextLine());
        String[] split = line.split(",");
        int count = -1;
        for (int i = 0; i < split.length; i++) {
            // 连续子串累加值
            int sum = 0;
            // 记录起始位置
            int j = i;
            // 子循环,寻找符合条件的子串
            while (j < split.length) {
                sum += Integer.parseInt(split[j]);
                // 小于目标值,则向后走一位
                if (sum < num) {
                    j++;
                } else if (sum == num) { // 等于目标值,记录长度,只保留最大值
                    count = Math.max(count, j - i + 1);
                } else { // 超出目标值,退出子循环,从下个数开始
                    break;
                }
            }
        }
        System.out.println(count);
    }

43.整数编码

  实现一个整数编码方法
  使得待编码的数字越小
  编码后所占用的字节数越小
  编码规则如下
  1.编码时7位一组,每个字节的低7位用于存储待编码数字的补码
  2.字节的最高位表示后续是否还有字节,置1表示后面还有更多的字节,
  置0表示当前字节为最后一个字节
  3.采用小端序编码,低位和低字节放在低地址上
  4.编码结果按16进制数的字符格式进行输出,小写字母需要转化为大写字母
 
  输入描述
  输入的为一个字符串表示的非负整数
  输出描述
  输出一个字符串表示整数编码的16进制码流
 
  示例一
  输入
  0
  输出
  00
  说明:输出的16进制字符不足两位的前面补零
 
  示例二
  输入
  100
  输出
  64
  说明:100的二进制表示为0110 0100只需一个字节进行编码
  字节的最高位0,剩余7位存储数字100的低7位(1100100)所以编码后的输出为64
 
  示例三
  输入
  1000
  输出
  E807
  说明
  1000的二进制表示为 0011 1110 1000 至少需要两个字节进行编码
  第一个字节最高位是1 剩余7位存储数字 1000的低7位(1101000)
  所以第一个字节的二进制位(1110 1000)即E8
  第二个字节最高位置0 剩余的7位存储数字 1000的第二个低7位(0000111)
  所以第一个字节的二进制为(0000 0111)即07
  采用小端序编码 所以低字节E8输出在前面
  高字节07输出在后面
 
  备注
  代编码数字取值范围为 [0,1<<64-1]
    // 整数编码
    // 解题思路:将输入的数转为二进制数,从后往前依次截取7位,根据要求拼接0或1,在把每个结果拼接起来
    // 小端序编码 大概意思就是原来低位放在高位,高位放在低位,就是颠倒过来。在这里的意思就是低位转的放在前面,越高位转的放在越后面(可能理解有误)
    // 代码通过率没有100%,自己的测试数据都能过,暂不知道原因,能看出异常的请告诉我!!!
    public static void test043() {
        Scanner sc = new Scanner(System.in);
        int input = sc.nextInt();
        // 将输入的数字转为二进制
        String binaryValue = Integer.toBinaryString(input);
        int len = binaryValue.length();
        if (len <= 7) {
            int parseInt = Integer.parseInt("0" + binaryValue, 2);
            System.out.println(tenTo16(parseInt));
            return;
        }
        int count = len / 7;
        // 存放结果
        String res = "";
        for (int i = 0; i < count; i++) {
            // 存储每7位的十进制数
            int num = 0;
            // 从后往前截取7位
            String lastStr = binaryValue.substring(len - 7 * (i + 1), len - 7 * i);
            // 前几位
            if (i == count - 1) {
                // len % 7 == 0 说明没有了,所以补0
                if (len % 7 == 0) {
                    // 拼接0
                    num = Integer.parseInt("0" + lastStr, 2);
                } else {
                    // 拼接1
                    num = Integer.parseInt("1" + lastStr, 2);
                }

            } else { // 其他的补1
                // 拼接1
                num = Integer.parseInt("1" + lastStr, 2);
            }
            // 小端序
            res = res + tenTo16(num);
        }
        // 取最前的几位
        if (len % 7 != 0) {
            int numTen = Integer.parseInt(binaryValue.substring(0, len - 7 * count), 2);
            String s = tenTo16(numTen);
            res = res + s;
        }
        System.out.println(res);
    }

    /**
     * 十进制转十六进制
     *
     * @return
     */
    private static String tenTo16(int num) {
        String s = "";
        do {
            int res = num % 16;
            num = num / 16;
            if (res == 15) {
                s = "F" + s;
            } else if (res == 14) {
                s = "E" + s;
            } else if (res == 13) {
                s = "D" + s;
            } else if (res == 12) {
                s = "C" + s;
            } else if (res == 11) {
                s = "B" + s;
            } else if (res == 10) {
                s = "A" + s;
            } else {
                s = res + s;
            }
        } while (num != 0);
        if (s.length() == 1) {
            return "0" + s;
        }
        return s;
    }
    
   /**
     * 任何进制转10进制
     * 十进制转二进制
     * 十进制转十六进制
     */
    public void study() {
        // 任何进制数转10进制,第一个参数:要转的字符串; 第二个参数:要转的字符串的进制数
        int parseInt = Integer.parseInt("110", 2);
        // 十进制转二进制
        String s = Integer.toBinaryString(123);
        // 十进制转十六进制,十六进制的字母是小写的
        String s1 = Integer.toHexString(123);
        // 字符串小写字母转大写
        String upperCase = s1.toUpperCase();
        // 字符串大写字母转小写
        String lowerCase = s1.toLowerCase();
    }

42.输出指定格式字符

  Vlan是一种为局域网设备进行逻辑划分的技术
  为了标识不同的vlan 引入了vlan id 1~4094之间的整数
  定义一个vlan id 的资源池
  资源池中连续的vlan用开始vlan-结束vlan表示,
  不连续的用单个整数表示
  所有的vlan用英文逗号连接起来
  现有一个vlan资源池,业务需要从资源池中申请一个vlan
  需要你输出从vlan资源池中移除申请的vlan后的资源池

  输入描述
  第一行为字符串格式的vlan资源池
  第二行为业务要申请的vlan vlan的取值范围1~4094

  输出描述
  从输入vlan资源池中移除申请的vlan后
  字符串格式的vlan资源池
  输出要求满足题目中要求的格式,
  并且要求从小到大升序输出
  如果申请的vlan不在原资源池,输出升序排序的原资源池的字符串即可

  示例一
  输入
  1-5
  2
  输出
  1,3-5
  说明:原vlan资源池中有1 2 3 4 5 移除2后
  剩下的1 3 4 5按照升序排列的方式为 1 3-5

  示例二
  输入
  20-21,15,18,30,5-10
  15
  输出
  5-10,18,20-21,30
  说明:
  原vlan资源池中有5 6 7 8 9 10 15 18 20 21 30
  移除15后 剩下的为 5 6 7 8 9 10 18 20 21 30
  按照题目描述格式并升序后的结果为5-10,18,20-21,30

  示例三
  输入
  5,1-3
  10
  输出
  1-3,5
  资源池中有1 2 3 5
  申请的资源不在资源池中
  将原池升序输出为1-3,5

  输入池中vlan数量范围为2~2094的整数
  资源池中vlan不重复且合法1~2094的整数
  输入是乱序的
    // 输出指定格式字符
    // 解题思路:用一个集合,存储每一个拆开后的每一个数字,移除目标数字后进行排序,遍历集合,组装连续的数字
    public static void test042() {
        Scanner sc = new Scanner(System.in);
        String line = sc.nextLine();
        int num = sc.nextInt();
        // 将输入的字符串根据,分割成数组
        String[] split = line.split(",");
        List<Integer> list = new ArrayList<>();
        // 遍历数组
        for (int i = 0; i < split.length; i++) {
            String str = split[i];
            // 将数组每一个字符拆成数组存进新集合中
            if (str.contains("-")) {
                String[] split1 = str.split("-");
                int start = Integer.parseInt(split1[0]);
                int end = Integer.parseInt(split1[1]);
                for (int j = start; j <= end; j++) {
                    list.add(j);
                }
            } else {
                list.add(Integer.parseInt(str));
            }
        }
        // 移除目标数字
        list.remove((Integer) num);
        // 对数组进行排序
        Collections.sort(list);
        // 存放结果
        StringBuilder sb = new StringBuilder();
        // 遍历集合,组装连续的数字
        for (int i = 0; i < list.size(); i++) {
            int start = i;
            while (i + 1 < list.size() && list.get(i) + 1 == list.get(i + 1)) {
                i++;
            }
            // 单个数字
            if (start == i) {
                sb.append(list.get(start) + ",");
            } else { // 连续的数字
                sb.append(list.get(start) + "-" + list.get(i) + ",");
            }
        }
        System.out.println(sb.substring(0, sb.length() - 1));

    }

40.小朋友分班

  幼儿园两个班的小朋友排队时混在了一起
  每个小朋友都知道自己跟前面一个小朋友是不是同班
  请你帮忙把同班的小朋友找出来
  小朋友的编号为整数
  与前面一个小朋友同班用Y表示
  不同班用N表示
  输入描述:
  输入为空格分开的小朋友编号和是否同班标志
  比如 6/N 2/Y 3/N 4/Y
  表示一共有4位小朋友
  2和6是同班 3和2不同班 4和3同班
  小朋友总数不超过999
  0< 每个小朋友编号 <999
  不考虑输入格式错误
 
  输出两行
  每一行记录一班小朋友的编号  编号用空格分开
  并且
  1. 编号需要按照大小升序排列,分班记录中第一个编号小的排在第一行
  2. 如果只有一个班的小朋友 第二行为空
  3. 如果输入不符合要求输出字符串ERROR
 
  示例:
  输入
  1/N 2/Y 3/N 4/Y
  输出
  1 2
  3 4
  说明:2的同班标记为Y因此和1同班
  3的同班标记位N因此和1,2不同班
  4的同班标记位Y因此和3同班
    // 小朋友分班
    // 解题思路:用一个LinkedHashMap存储小朋友编号和Y/N,遍历map,用两个集合存放不同班的小朋友,判断小朋友应该加入哪个list
    public static void test040() {
        Scanner sc = new Scanner(System.in);
        String line = sc.nextLine();
        // map key存储每一个小朋友的编号,value存储N/Y。用LinkedHashMap是因为它是有序的,按插入顺序排序
        Map<Integer, String> map = new LinkedHashMap<>();
        try {
            String[] split = line.split(" ");
            for (int i = 0; i < split.length; i++) {
                String str = split[i];
                String[] split1 = str.split("/");
                // 第一个小朋友必须是N
                if (i == 0 && "Y".equals(split1[1])) {
                    System.out.println("ERROR");
                    return;
                }
                // 不是N/Y,或重复出现,报错
                if (!("N".equals(split1[1]) || "Y".equals(split1[1])) || map.containsKey(Integer.parseInt(split1[0]))) {
                    System.out.println("ERROR");
                    return;
                }
                map.put(Integer.parseInt(split1[0]), split1[1]);
            }
            // 用两个list存储两个班的小朋友
            List<Integer> list1 = new ArrayList<>();
            List<Integer> list2 = new ArrayList<>();
            // 先存第一个小朋友
            list1.add(Integer.parseInt(line.substring(0, line.indexOf("/"))));
            // 从map中移除第一个小朋友
            map.remove(Integer.parseInt(line.substring(0, line.indexOf("/"))), "N");
            // 用来判断小朋友应该加入哪个list
            boolean flag = true;
            // 遍历map,当flag=true,key=Y时,加入list1;key=N时,加入list2,且flag=false。当flag=false,key=Y时,加入list2;key=N时,加入list1,且flag=true。
            for (Integer s : map.keySet()) {
                if (flag) {
                    if ("Y".equals(map.get(s))) {
                        list1.add(s);
                    } else {
                        list2.add(s);
                        flag = false;
                    }
                } else {
                    if ("Y".equals(map.get(s))) {
                        list2.add(s);
                    } else {
                        list1.add(s);
                        flag = true;
                    }

                }
            }
            // 对list进行排序
            Collections.sort(list1);
            Collections.sort(list2);
            for (int k = 0; k < list1.size(); k++) {
                System.out.print(list1.get(k) + " ");
            }
            System.out.println();
            for (int k = 0; k < list2.size(); k++) {
                System.out.print(list2.get(k) + " ");
            }

        } catch (Exception e) {
            System.out.println("ERROR");
            return;
        }

    }

39.数列解析

  有一个数列A[n]
  从A[0]开始每一项都是一个数字
  数列中A[n+1]都是A[n]的描述
  其中A[0]=1
  规则如下
  A[0]:1
  A[1]:11 含义其中A[0]=1是1个1 即11
  表示A[0]从左到右连续出现了1次1
  A[2]:21 含义其中A[1]=11是2个1 即21
  表示A[1]从左到右连续出现了2次1
  A[3]:1211 含义其中A[2]从左到右是由一个2和一个1组成 即1211
  表示A[2]从左到右连续出现了一次2又连续出现了一次1
  A[4]:111221  含义A[3]=1211 从左到右是由一个1和一个2两个1 即111221
  表示A[3]从左到右连续出现了一次1又连续出现了一次2又连续出现了2次1
 
  输出第n项的结果
  0<= n <=59
  输入描述:
  数列第n项   0<= n <=59
  4
  输出描述
  数列内容
  111221
    // 数列解析
    // 解题思路:根据A[0]循环求出A[1]、A[2]....
    public static void test039() {
        Scanner sc = new Scanner(System.in);
        int num = sc.nextInt();
        if (num == 0) {
            System.out.println(1);
            return;
        }
        // 初始值A[0]
        String s = "1";
        StringBuilder sb = new StringBuilder();
        for (int i = 1; i <= num; i++) {
            char[] chars = s.toCharArray();
            // 遍历字符串的每个字符
            for (int j = 0; j < chars.length; j++) {
                int start = j;
                // 相同字符
                while (j + 1 < chars.length && chars[j] == chars[j + 1]) {
                    j++;
                }
                // 只有一个
                if (start == j) {
                    sb.append(1).append(chars[j]);
                } else { // 有多个
                    sb.append(j - start + 1).append(chars[j]);
                }
            }
            // 替换初始值
            s = sb.toString();
            // 置空
            sb = new StringBuilder();
        }
        System.out.println(s);
    }

38. url拼接

  给定一个url前缀和url后缀
  通过,分割 需要将其连接为一个完整的url
  如果前缀结尾和后缀开头都没有/
  需要自动补上/连接符
  如果前缀结尾和后缀开头都为/
  需要自动去重
  约束:
  不用考虑前后缀URL不合法情况
 
  输入描述
  url前缀(一个长度小于100的字符串)
  url后缀(一个长度小于100的字符串)
  输出描述
  拼接后的url
 
  一、
  输入
  /acm,/bb
  输出
  /acm/bb
 
  二、
  输入
  /abc/,/bcd
  输出
  /abc/bcd
 
  三、
  输入
  /acd,bef
  输出
  /acd/bef
 
  四、
  输入
  ,
  输出
  /
    // url拼接
    public static void test038() {
        Scanner in = new Scanner(System.in);
        String line = in.nextLine();
        in.close();

        String[] split = line.split(",");
        if (split.length == 0) {
            System.out.println("/");
            return;
        }

        String combine = split[0] + "/" + split[1];
        // 如果出现多个/,则替换成/
        String url = combine.replaceAll("/+", "/");
        System.out.println(url);
    }

36.满足最低能力值的数量

  用数组代表每个人的能力
  一个比赛活动要求 参赛团队的最低能力值为N
  每个团队可以由一人或者两人组成
  且一个人只能参加一个团队
  计算出最多可以派出多少只符合要求的队伍
 
  输入描述
  5
  3 1 5 7 9
  8
  第一行代表总人数,范围  1~500000
  第二行数组代表每个人的能力
  数组大小范围 1~500000
  元素取值范围 1~500000
  第三行数值为团队要求的最低能力值
  1~500000
 
  输出描述
  3
  最多可以派出的团队数量
 
  示例一
  输入
  5
  3 1 5 7 9
  8
 
  输出
  3
 
  说明 3、5组成一队   1、7一队  9自己一队  输出3
 
  7
  3 1 5 7 9 2 6
  8
  输出
  4
 
  3
  1 1 9
  8
  输出
  1
    // 满足最低能力值的数量
    // 解题思路:遍历输入的数组,记录大于N的值的数量,将小于N的放进集合里,对集合进行排序,采用双指针,筛选大于N的组合
    public static void test036() {
        Scanner sc = new Scanner(System.in);
        int len = Integer.parseInt(sc.nextLine());
        String[] split = sc.nextLine().split(" ");
        int requireValue = Integer.parseInt(sc.nextLine());
        List<Integer> list = new ArrayList<>();
        // 大于N的值的数量
        int count = 0;
        for (int i = 0; i < len; i++) {
            int num = Integer.parseInt(split[i]);
            if (num >= requireValue) {
                count++;
            } else {
                list.add(num);
            }
        }
        // 对集合进行排序
        Collections.sort(list);
        // 双指针
        // 头指针:集合头
        int start = 0;
        // 尾指针:数组尾
        int end = list.size() - 1;
        while (start < end) {
            // 当头尾指针之和满足要求,count++,头指针向前移动一步,尾指针向后移动一步
            if (list.get(start) + list.get(end) >= requireValue) {
                count++;
                start++;
                end--;
            } else { // 当头尾指针之和不满足要求,头指针向前移动一步,尾指针不变
                start++;
            }
        }
        System.out.println(count);
    }

更多华为od机试题请点这里<华为od机试题6 真题>,每篇8题,有更多的题也请告诉我啊

最后

以上就是高兴万宝路为你收集整理的华为od机试题5 真题的全部内容,希望文章能够帮你解决华为od机试题5 真题所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(44)

评论列表共有 0 条评论

立即
投稿
返回
顶部