华为od机试题9 真题

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

9.寻找重复字符

题目描述:
给定两个字符串,
从字符串2中找出字符串1中的所有字符,
去重并按照ASCII码值从小到大排列,

输入描述
字符范围满足ASCII编码要求,
输入字符串1长度不超过1024,
字符串2长度不超过100

输出描述
按照ASCII由小到大排序

示例一
输入
bach
bbaaccddfg

输出
abc

示例二
输入
fach
bbaaccedfg

输出
acf
// 寻找重复字符
    public static void test009() {
        Scanner scanner = new Scanner(System.in);
        String line1 = scanner.nextLine();
        String line2 = scanner.nextLine();
        List<Character> list = new ArrayList<>();
        // 将输入的字符串转为字符数组
        for (int i = 0; i < line2.length(); i++) {
            list.add(line2.charAt(i));
        }
        // 用来存第一第二次输入都有的字符
        List<Character> resList = new ArrayList<>();
        for (int i = 0; i < line1.length(); i++) {
            char c = line1.charAt(i);
            // &&后的条件是防止重复
            if (list.contains(c) && !resList.contains(c)) {
                resList.add(c);
            }
        }
        // 对集合进行排序,默认是按ASCII码值排序
        Collections.sort(resList);
        for (Character c : resList) {
            System.out.print(c);
        }
    }

7.字符串翻转

 输入一个英文文章片段
 翻转指定区间的单词顺序,标点符号和普通字母一样处理
 例如输入字符串 "I am a developer."
 区间[0,3]则输出 "developer. a am I"

 输入描述:
 使用换行隔开三个参数
 第一个参数为英文文章内容即英文字符串
 第二个参数为反转起始单词下标,下标从0开始
 第三个参数为结束单词下标,

 输出描述
 反转后的英文文章片段,所有单词之间以一个半角空格分割进行输出

 示例一:
 输入
 I am a developer.
 1
 2
 输出
 I a am developer.

 示例二:
 输入
 Hello world!
 0
 1
 输出
 world! Hello

 说明:
 输入字符串可以在前面或者后面包含多余的空格,
 但是反转后的不能包含多余空格

 示例三:
 输入:
 I am a developer.
 0
 3
 输出
 developer. a am I

 说明:
 如果两个单词见有多余的空格
 将反转后单词间的空格减少到只含一个

 示例四:
 输入
 Hello!
 0
 3
 输出
 EMPTY

 说明:
 指定反转区间只有一个单词,或无有效单词则统一输出EMPTY
// 字符串翻转
    public static void test007() {
        Scanner sc = new Scanner(System.in);
        String line = sc.nextLine();
        int start = sc.nextInt();
        int end = sc.nextInt();
        // 去掉前后的空格
        line = line.trim();
        String[] split = line.split(" ");
        // 如果起始数小于0,取0
        start = Math.max(start, 0);
        // 如果结束数大于数组长度,取数组最后一个
        end = Math.min(end, split.length - 1);
        // 指定反转区间只有一个单词,或无有效单词则统一输出EMPTY
        if (start >= end || start >= split.length - 1 || end <= 0) {
            System.out.println("EMPTY");
            return;
        }
        // 进行字符串翻转,直至重合
        while (start < end){
            String temp = split[start];
            split[start] = split[end];
            split[end] = temp;
            start++;
            end--;
        }
        //拼接字符串
        StringBuilder sb = new StringBuilder();
        for (String s : split) {
            sb.append(s + " ");
        }
        // 去掉末尾的空格
        System.out.println(sb.toString().trim());
    }

6.小朋友身高排序

题目描述:
 小明今年升学到了小学一年级,
 来到新班级后,发现其他小朋友身高参差不齐,
 然后就想基于各小朋友和自己的身高差,对他们进行排序,
 请帮他实现排序

 输入描述
 第一行为正整数 H和N
 0 < H < 200 为小明的身高
 0 < H < 50 为新班级其他小朋友个数
 第二行为N个正整数
 H1 ~ Hn分别是其他小朋友的身高
 取值范围0 < Hi < 200
 且N个正整数各不相同

 输出描述
 输出排序结果,各正整数以空格分割
 和小明身高差绝对值最小的小朋友排在前面
 和小明身高差绝对值最大的小朋友排在后面
 如果两个小朋友和小明身高差一样
 则个子较小的小朋友排在前面

 示例一
 输入
 100 10
 95 96 97 98 99 101 102 103 104 105
 输出
 99 101 98 102 97 103 96 104 95 105
// 小朋友身高排序
    public static void test006() {
        Scanner sc = new Scanner(System.in);
        String line1 = sc.nextLine();
        String line2 = sc.nextLine();
        String[] input1 = line1.split(" ");
        String[] input2 = line2.split(" ");
        // 基准数
        int height = Integer.parseInt(input1[0]);
        // 人数
        int num = Integer.parseInt(input1[1]);
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < num; i++) {
            list.add(Integer.parseInt(input2[i]));
        }

        // list.sort() 自定义排序规则
        // 在 list.sort() 底层代码中,以 compare(list [ i - 1 ], list [ i ]) 形式调用该方法,
        // 当其的返回值大于0时,list [ i - 1 ] 将与 list [ i ] 交换位置
        list.sort((h1, h2) -> {
            // 与基准数的绝对值
            int diff1 = Math.abs(h1 - height);
            int diff2 = Math.abs(h2 - height);
            // 若与基准数的绝对值相等,则高的排在后,否则基准数大的排在后
            return diff1 == diff2 ? h1 - h2 : diff1 - diff2;
        });
        for (Integer h : list) {
            System.out.print(h + " ");
        }
    }

5.CPU最少执行时间

题目描述:
 为了充分发挥Gpu算力,
 需要尽可能多的将任务交给GPU执行,
 现在有一个任务数组,
 数组元素表示在这1s内新增的任务个数,
 且每秒都有新增任务,
 假设GPU最多一次执行n个任务,
 一次执行耗时1s,
 在保证Gpu不空闲的情况下,最少需要多长时间执行完成。

 输入描述
 第一个参数为gpu最多执行的任务个数
 取值范围1~10000
 第二个参数为任务数组的长度
 取值范围1~10000
 第三个参数为任务数组
 数字范围1~10000

 输出描述
 执行完所有任务需要多少秒

 示例一
 输入
 3
 5
 1 2 3 4 5
 输出
 6
 说明
 一次最多执行3个任务,最少耗时6s

 示例二
 输入
 4
 5
 5 4 1 1 1
 输出
 5
 说明
 一次最多执行4个任务,最少耗时5s
// CPU最少执行时间
    public static void test005() {
        Scanner sc = new Scanner(System.in);
        // 每秒执行任务数
        int qps = Integer.parseInt(sc.nextLine());
        int arrayLen = Integer.parseInt(sc.nextLine());
        String line = sc.nextLine();
        int[] array = new int[arrayLen];
        String[] strings = line.split(" ");
        for (int i = 0; i < arrayLen; i++) {
            array[i] = Integer.parseInt(strings[i]);
        }
        // 使用的时间
        int time = 0;
        // 剩余任务,初始为0
        int leaveTask = 0;
        for (int i = 0; i < arrayLen; i++) {
            // 若当前任务+剩余任务大于每秒执行任务,则剩余任务 = 之前剩余任务 + 当前任务 - 每秒执行任务
            if (array[i] + leaveTask > qps) {
                leaveTask = array[i] + leaveTask - qps;
            } else {
                leaveTask = 0;
            }
            // 累加时间
            time++;
        }
        // 当数组走完后还有剩余任务,用剩余任务/每秒执行任务算出需要的时间
        if (leaveTask > 0) {
            int res = leaveTask / qps;
            time = time + res;
            if (leaveTask % qps != 0) {
                time++;
            }
        }
        System.out.println(time);
    }

4.猴子爬山

题目描述:
 一天一只顽猴想要从山脚爬到山顶
 途中经过一个有n个台阶的阶梯,但是这个猴子有个习惯,每一次只跳1步或3步
 试问?猴子通过这个阶梯有多少种不同的跳跃方式

 输入描述
 输入只有一个这个数n 0 < n < 50
 此阶梯有多个台阶

 输出描述
 有多少种跳跃方式

 示例一
 输入
 50
 输出
 122106097
 示例二
 输入
 3
 COPY
 输出
 2
/**
     * 解题思路:
     * 动态规划题,找规律
     * n = 1  1
     * n = 2  1
     * n = 3  2
     * n = 4  3
     * n = 5  4
     * n = 6  6
     * n = 7  9
     * 可得当n > 3时 f(n) = f(n - 1) + f(n - 3)
     * 所以可以用递归,n = 1/2/3 时值是固定的,为递归结束条件
     */
    // 猴子爬山
    public static void test004() {
        Scanner sc = new Scanner(System.in);
        int nums = sc.nextInt();
        int value = fun(nums);
        System.out.println(value);
    }
    private static int fun(int nums) {
        // 递归结束条件
        if (nums == 1 || nums == 2) {
            return 1;
        }
        // 递归结束条件
        if (nums == 3) {
            return 2;
        }
        // 规律
        return fun(nums - 1) + fun(nums - 3);
    }

3.输出信元的值

题目描述:
 TLV编码是按TagLengthValue格式进行编码的,一段码流中的信元用tag标识,tag在码流中唯一不重复,
 length表示信元value的长度,value表示信元的值,码流以某信元的tag开头,
 tag固定占一个字节,length固定占两个字节,字节序为小端序,
 现给定tlv格式编码的码流以及需要解码的信元tag,请输出该信元的value。

 输入码流的16进制字符中,不包括小写字母;
 且要求输出的16进制字符串中也不要包含小写字母;
 码流字符串的最大长度不超过50000个字节。

 输入描述
 第一行为第一个字符串 ,表示待解码信元的tag;
 输入第二行为一个字符串, 表示待解码的16进制码流;
 字节之间用空格分割。

 输出描述
 输出一个字符串,表示待解码信元以16进制表示的value。

 示例一
 输入
 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。
// 输出信元的值
    public static void test003() {
        Scanner sc = new Scanner(System.in);
        String tag = sc.nextLine();
        String line = sc.nextLine();
        int len = line.length();
        int p = 0;
        while (p < len) {
            // value的长度  后两位拼接前两位,16进制,需要转换为10进制
            int length = Integer.parseInt(line.substring(p + 6, p + 8) + line.substring(p + 3, p + 5), 16);
            // 找到目标值
            if (tag.equals(line.substring(p, p + 2))) {
                String value = line.substring(p + 9, p + 9 + (length * 3 - 1));
                System.out.println(value);
                return;
            }
            // 动态算出p应该移动几位,tag和length是固定的,value根据length决定,要注意空格
            p += 9 + length * 3;
        }
    }

2.指定元素对最小和

 题目描述:
 给定两个整数数组,arr1、arr2,数组元素按升序排列;
 假设从arr1、arr2中分别取出一个元素,可构成一对元素;
 现在需要取出k对元素,并对取出的所有元素求和,计算和的最小值;
 注意:两对元素对应arr1、arr2的下标是相同的,视为同一对元素。

 输入描述
 输入两行数组arr1、arr2
 每行首个数字为数组大小size, 0 < size <= 100
 arr1,arr2中的每个元素e, 0< e <1000
 接下来一行,正整数k 0 < k <= arr1.size * arr2.size

 输出描述
 满足要求的最小值

 示例一
 输入

 1 1 2
 1 2 3
 2
 输出
 4
 说明:
 用例中需要取两个元素,取第一个数组第0个元素与第二个数组第0个元素组成一个元素[1,1];
 取第一个数组第1个元素与第二个数组第0个元素组成一个元素[1,1];
 求和为1+1+1+1=4 ,满足要求最小
// 指定元素对最小和
    // 思路:双层for循环,求出两个数组所有值一一相加的值,放进另一个数组中,并进行升序排序,求出指定前几个的和
    public static void test002() {
        Scanner sc = new Scanner(System.in);
        String line1 = sc.nextLine();
        String line2 = sc.nextLine();
        int[] array1 = stringToArray(line1);
        int[] array2 = stringToArray(line2);
        int len1 = array1.length;
        int len2 = array2.length;
        int groupCount = sc.nextInt();
        List<Integer> list = new ArrayList();
        // 双层for循环,求出两个数组所有值一一相加的值,放进另一个数组中
        for (int i = 0; i < len1; i++) {
            for (int j = 0; j < len2; j++) {
                list.add(array1[i] + array2[j]);
            }
        }
        // 对集合进行排序(升序)
        Collections.sort(list);
        int res = 0;
        // 求出指定前几个的和
        for (int i = 0; i < groupCount; i++) {
            res += list.get(i);
        }
        System.out.println(res);
    }
 private static int[] stringToArray(String line) {
        String[] strings = line.split(" ");
        int[] array = new int[strings.length];
        for (int i = 0; i < strings.length; i++) {
            array[i] = Integer.parseInt(strings[i]);
        }
        return array;
 }

1.勾股数元组

  题目描述:
 如果三个正整数A、B、C ,A²+B²=C²则为勾股数
 如果ABC之间两两互质,即A与B,A与C,B与C均互质没有公约数,
 则称其为勾股数元组。
 请求出给定n~m范围内所有的勾股数元组

 输入描述
 起始范围
 1 < n < 10000
 n < m < 10000

 输出描述
 ABC保证A<B<C
 输出格式A B C
 多组勾股数元组,按照A B C升序的排序方式输出。
 若给定范围内,找不到勾股数元组时,输出Na。

 示例一
 输入
 1
 20
 输出
 3 4 5
 5 12 13
 8 15 17
 示例二
 输入
 5
 10
 输出
 Na
// 解题思路:双层for循环,求出所有勾股数元组,在筛选出符合条件的
    // 勾股数元组
    public static void test001() {
        Scanner sc = new Scanner(System.in);
        int num1 = sc.nextInt();
        int num2 = sc.nextInt();
        boolean flag = true;
        for (int i = num1; i < num2; i++) {
            for (int j = i + 1; j <= num2; j++) {
                // pow():取几次方,0.5次方相当于开根号
                double res = Math.pow(i, 2) + Math.pow(j, 2);
                double pow = Math.pow(res, 0.5);
                // 结果小于nums且是整数    判断一个double型数据是不是整数:Math.abs(pow - Math.round(pow)) < Double.MIN_VALUE
                if (pow <= num2 && Math.abs(pow - Math.round(pow)) < Double.MIN_VALUE) {
                    int powRes = (int) pow;
                    // 两两互质
                    if (isSingle(i, j) && isSingle(i, powRes) && isSingle(j, powRes)) {
                        System.out.println(i + " " + j + " " + powRes);
                        flag = false;
                    }
                }
            }
        }
        if (flag) {
            System.out.println("Na");
        }
    }
    
	/**
     * 判断两个数字是否互质 (没有相同的公约数)
     *
     * @param num1
     * @param num2
     * @return
     */
    private static boolean isSingle(int num1, int num2) {
        int res = Math.min(num1, num2);
        for (int i = 2; i <= res; i++) {
            if (num1 % i == 0 && num2 % i == 0) {
                return false;
            }
        }
        return true;
    }
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chenzm666666

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值