华为od机试题4 真题

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

58.处理所有作业总时长

  一个工厂有m条流水线
  来并行完成n个独立的作业
  该工厂设置了一个调度系统
  在安排作业时,总是优先执行处理时间最短的作业
  现给定流水线个数m
  需要完成的作业数n
  每个作业的处理时间分别为 t1,t2...tn
  请你编程计算处理完所有作业的耗时为多少
  当n>m时 首先处理时间短的m个作业进入流水线
  其他的等待
  当某个作业完成时,
  依次从剩余作业中取处理时间最短的
  进入处理

  输入描述:
  第一行为两个整数(采取空格分隔)
  分别表示流水线个数m和作业数n
  第二行输入n个整数(采取空格分隔)
  表示每个作业的处理时长 t1,t2...tn
  0<m,n<100
  0<t1,t2...tn<100

  输出描述
  输出处理完所有作业的总时长

  案例
  输入
  3 5
  8 4 3 2 10
  输出
  13
  说明
  先安排时间为2,3,4的三个作业
  第一条流水线先完成作业
  调度剩余时间最短的作业8
  第二条流水线完成作业
  调度剩余时间最短的作业10
  总共耗时 就是二条流水线完成作业时间13(3+10)

  输入
  3 9
  1 1 1 2 3 4 6 7 8
  输出
  13
    // 处理所有作业的总时长
    // 解题思路:对数组进行排序,累加每条流水线分配的任务的时长,输出最大的
    public static void test058() {
        Scanner sc = new Scanner(System.in);
        String line1 = sc.nextLine();
        String line2 = sc.nextLine();
        String[] split1 = line1.split(" ");
        // 流水线个数m和作业数n
        int m = Integer.parseInt(split1[0]);
        int n = Integer.parseInt(split1[1]);
        String[] split2 = line2.split(" ");
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < split2.length; i++) {
            list.add(Integer.parseInt(split2[i]));
        }
        // 对数组进行排序
        Collections.sort(list);
        // 作业数n小于等于流水线个数m,则结果为排序后的最后一个值
        if (n <= m) {
            System.out.println(list.get(list.size() - 1));
            return;
        }
        // 结果
        int res = 0;
        // 遍历每一条流水线
        for (int k = 0; k < m; k++) {
            // 每条流水线获取到的任务时长总和
            int allTime = 0;
            // 累加每条流水线获取到的任务时长
            for (int i = k; i < list.size(); i += m) {
                allTime += list.get(i);
            }
            // 取最大的
            res = Math.max(allTime, res);
        }
        System.out.println(res);
    }

53.最大停车距离

 停车场有一横排车位0代表没有停车,1代表有车.
 至少停了一辆车在车位上,也至少有一个空位没有停车.
 为防止刮蹭,需为停车人找到一个车位
 使得停车人的车最近的车辆的距离是最大的
 返回此时的最大距离

 输入描述:
 1. 一个用半角逗号分割的停车标识字符串,停车标识为0或1,
 0为空位,1为已停车
 2. 停车位最多有100个

 输出描述
 1. 输出一个整数记录最大距离

 示例一:
 输入
 1,0,0,0,0,1,0,0,1,0,1

 输出
 2

 说明
 当车停在第三个位置上时,离其最近的车距离为2(1~3)
 当车停在第四个位置上时,离其最近的车距离为2(4~6)
 其他位置距离为1
 因此最大距离为2
    // 最大停车距离
    // 解题思路:取出所有已停车的位置的索引,计算其与停车场头的距离、停车场尾的距离、两车之间的距离/2,输出最大的值
    public static void test053(){
        Scanner sc = new Scanner(System.in);
        String line = sc.nextLine();
        String[] split = line.split(",");
        // 存放停车位置的索引
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < split.length; i++) {
            int num = Integer.parseInt(split[i]);
            if (1 == num) {
                list.add(i);
            }
        }
        // 第一辆车与停车场头的距离
        int startLen = list.get(0);
        // 最后一辆车与停车场尾的距离
        int endLen = split.length - 1 - list.get(list.size() - 1);
        int res = 0;
        for (int i = 0; i < list.size() - 1; i++) {
            // 停车后与左右车的最小距离
            int len = (list.get(i + 1) - list.get(i)) / 2;
            res = Math.max(res, len);
        }
        // 最大距离
        System.out.println(Math.max(res,Math.max(startLen, endLen)));
    }

52.磁盘容量排序

 磁盘的容量单位有M,G,T这三个等级
 他们之间的换算关系为
 1T=1024G
 1G=1024M
 现在给定N块磁盘的容量
 请对他们按从小到大的顺序进行稳定排序
 例如给定5块盘容量
 1T,20M,3G,10G6T,3M12G9M
 排序后的结果为20M,3G,3M12G9M,1T,10G6T
 注意单位可以重复出现
 上述3M12G9M为 3M+12G+9M和 12M12G相等

 输入描述:
 输入第一行包含一个整数N
 2<=N<=100 ,表示磁盘的个数
 接下来的N行每行一个字符串 长度 (2<l<30)
 表示磁盘的容量
 有一个或多个格式为 mv的子串组成
 其中m表示容量大小 v表示容量单位
 例如
 磁盘容量m的范围 1~1024正整数
 容量单位v的范围包含题目中提到的M,G,T
 输出描述:
 输出N行
 表示N块磁盘容量排序后的结果

 示例1:
 输入
 3
 1G
 2G
 1024M
 输出
 1G
 1024M
 2G
 说明 1G和1024M容量相等,稳定排序要求保留他们原来的相对位置
 故1G在1024M前

 示例二:
 输入
 3
 2G4M
 3M2G
 1T
 输出
 3M2G
 2G4M
 1T
 说明1T大于2G4M大于3M2G
    // 磁盘容量排序
    // 解题思路:将输入的值放在集合中,将每个元素都转换为M为单位,在进行比较排序
    public static void test052_2() {
        Scanner sc = new Scanner(System.in);
        int len = Integer.parseInt(sc.nextLine());
        List<String> list = new ArrayList<>();
        for (int i = 0; i < len; i++) {
            list.add(sc.nextLine());
        }
        list.sort((s1, s2) -> {
            // 复杂的写法,使用双层循环分别求出每个数字和字母
            char[] chars1 = s1.toCharArray();
            char[] chars2 = s2.toCharArray();
            // 使用long型防止int型不够用
            long allNum1 = 0;
            long allNum2 = 0;
            for (int i = 0; i < chars1.length; i++) {
                String num = "";
                // 判断是否是数字->获得字母前的数字
                while (i < chars1.length && Character.isDigit(chars1[i])) {
                    // 拼接数字
                    num = num + chars1[i];
                    i++;
                }
                if (chars1[i] == 'M') {
                    allNum1 += Integer.parseInt(num);
                } else if (chars1[i] == 'G') {
                    allNum1 += Integer.parseInt(num) * 1024;
                } else {
                    allNum1 += Integer.parseInt(num) * 1024 * 1024;
                }
            }
            for (int i = 0; i < chars2.length; i++) {
                String num = "";
                // 判断是否是数字->获得字母前的数字
                while (i < chars2.length && Character.isDigit(chars2[i])) {
                    // 拼接数字
                    num = num + chars2[i];
                    i++;
                }
                if (chars2[i] == 'M') {
                    allNum2 += Integer.parseInt(num);
                } else if (chars2[i] == 'G') {
                    allNum2 += Integer.parseInt(num) * 1024;
                } else {
                    allNum2 += Integer.parseInt(num) * 1024 * 1024;
                }
            }
            // 比较两个long型数据,x > y 返回1,x < y返回-1,x = y返回0
            return Long.compare(allNum1, allNum2);
        });
        for (String s : list) {
            System.out.println(s);
        }
    }

    // 巧妙的解法
    public static void test052() {
        Scanner sc = new Scanner(System.in);
        int len = Integer.parseInt(sc.nextLine());
        List<String> list = new ArrayList<>();
        for (int i = 0; i < len; i++) {
            list.add(sc.nextLine());
        }
        // 对数组进行排序
        list.sort((s1, s2) -> {
            long num1 = toNumber(s1);
            long num2 = toNumber(s2);
            // 比较两个long型数据,x > y 返回1,x < y返回-1,x = y返回0
            return Long.compare(num1, num2);
        });
        for (String s : list) {
            System.out.println(s);
        }
    }

   /**
     * 将字符串转为具体多少M,返回一个long型数字
     *
     * @return
     */
    private static long toNumber(String s) {
        // 正则表达式:根据字母M或G或T进行分割
        String[] numArray = s.split("[M|G|T]"); // 结果[1,2,3]
        // 正则表达式:根据1个或多个数字进行分割
        String[] letterArray = s.split("[0-9]+"); // 结果[,M,T,G] 因为字符串以数字开头,所以数组第一个是空
        // 返回的结果
        long sum = 0;
        for (int i = 1; i < letterArray.length; i++) {
            String letter = letterArray[i];
            long num = Long.parseLong(numArray[i - 1]);
            if ("M".equals(letter)) {
                sum += num;
            } else if ("G".equals(letter)) {
                sum += 1024 * num;
            } else if ("T".equals(letter)) {
                sum += 1024 * 1024 * num;
            }
        }
        return sum;
    }

51.非严格递增连续数字序列长度

  输入一个字符串仅包含大小写字母和数字
  求字符串中包含的最长的非严格递增连续数字序列长度
  比如:
  12234属于非严格递增数字序列
  示例:
  输入
  abc2234019A334bc
  输出
  4
  说明:
  2234为最长的非严格递增连续数字序列,所以长度为4
 
  输入
  aaaaaa44ko543j123j7345677781
  输出
  8
 
  输入
  aaaaa34567778a44ko543j123j71
  输出
  8
 
  输入
  345678a44ko543j123j7134567778aa
  输出
  9
 
  输入
  fwefksoSKJF12S45DS3DSAJKSldsf565441345sd1f87151234657812154341543
  输出
  5
    // 非严格递增连续数字序列长度
    // 解题思路:遍历每一个字符,按照规则计算非严格递增连续数字序列长度,保留最大长度
    public static void test051() {
        Scanner sc = new Scanner(System.in);
        String line = sc.nextLine();
        char[] chars = line.toCharArray();
        // 当前非严格递增长度
        int currentLen = 0;
        // 非严格递增最大长度
        int maxLen = 0;
        // 上一个字符,默认一个比数字大的
        char last = 'a';
        for (char c : chars) {
            if (Character.isDigit(c)) { // 当前字符是数字
                if (currentLen == 0) { // 当数字是开头时
                    currentLen++;
                } else if (c >= last) { // 符合非严格递增,当前非严格递增长度长度
                    currentLen++;
                } else { // 不符合非严格递增,保留最大的非严格递增长度
                    maxLen = Math.max(currentLen, maxLen);
                    // 初始化当前严格递增长度,因为当前是数字,所以其本身长度是1
                    currentLen = 1;
                }
                // 将当前数字置为上一个,用于比较
                last = c;
            } else { // 当前字符不是数字
                // 保留最大的非严格递增长度
                maxLen = Math.max(maxLen, currentLen);
                // 初始化当前严格递增长度
                currentLen = 0;
            }
        }
        System.out.println(maxLen);
    }

50.均分糖果

  小明从糖果盒中随意抓一把糖果
  每次小明会取出一半的糖果分给同学们
  当糖果不能平均分配时
  小明可以从糖果盒中(假设盒中糖果足够)取出一个或放回一个糖果
  小明至少需要多少次(取出放回和平均分配均记一次)能将手中糖果分至只剩一颗
  
  输入描述:
  抓取糖果数(小于1000000):15
  输出描述:
  最少分至一颗糖果的次数:5
  
  示例1:
  输入
  15
  输出
  5
  备注
  解释:(1) 15+1=16;
  (2) 16/2=8;
  (3) 8/2=4;
  (4) 4/2=2;
  (5) 2/2=1;
    // 这道题通过率好像只有85%,我也不知道原因
    // 均分糖果
    // 解题思路:当糖果数n不是偶数时,当(n + 1) / 2 % 2 == 0 说明num+1后除以2还是偶数,所以选择n+1,否则n-1
    public static void test050() {
        Scanner sc = new Scanner(System.in);
        int num = sc.nextInt();
        int count = 0;
        while (num != 1) {
            // 当num=3时,不符合一下规则,但是很容易算出是2次,所以直接加2并结束
            if (num == 3) {
                System.out.println(count + 2);
                return;
            }
            // 当num不是偶数
            if (num % 2 != 0) {
                // 当(num + 1) / 2 % 2 == 0 说明num+1后除以2还是偶数,所以选择+1,否则-1
                if ((num + 1) / 2 % 2 == 0) {
                    num++;
                } else {
                    num--;
                }
                // 无论是+1还是-1,count都要累加1
                count++;
            } else { // 当nums是偶数,除以2,count累加1
                num /= 2;
                count++;
            }
        }
        System.out.println(count);
    }

48.没有相同字符的元素长度乘积的最大值

  给定一个元素类型为小写字符串的数组
  请计算两个没有相同字符的元素长度乘积的最大值
  如果没有符合条件的两个元素返回0
  
  输入描述
  输入为一个半角逗号分割的小写字符串数组
  2<= 数组长度 <=100
  0< 字符串长度 <=50
  输出描述
  两个没有相同字符的元素长度乘积的最大值
  
  示例一
  输入
  iwdvpbn,hk,iuop,iikd,kadgpf
  输出
  14
  说明
  数组中有5个元组  第一个和第二个元素没有相同字符
  满足条件 输出7*2=14
    // 没有相同字符的元素长度乘积的最大值
    // 解题思路:一一比对元素,看一个元素是否包含另一个元素,如果没有则保留这两个元素的长度的乘积,保留最大的
    public static void test048() {
        Scanner sc = new Scanner(System.in);
        String line = sc.nextLine();
        String[] split = line.split(",");
        int sum = 0;
        for (int i = 0; i < split.length; i++) {
            for (int j = i + 1; j < split.length; j++) {
                // 两个元素有没有相同字符标识位
                boolean flag = true;
                String first = split[i];
                String next = split[j];
                // 遍历一个元素的全部字符
                for (int k = 0; k < first.length(); k++) {
                    // 判断是否包含这些字符
                    if (next.contains(first.charAt(k) + "")) {
                        // 有相同的字符
                        flag = false;
                        break;
                    }
                }
                // 没有相同的字符
                if (flag) {
                    // 计算两个元素长度的乘积,保留最大的
                    sum = Math.max(sum, first.length() * next.length());
                }
            }
        }
        System.out.println(sum);
    }

47. 相对开音节结构的子串个数

  相对开音节构成的结构为辅音+元音(aeiou)+辅音(r除外)+e
  常见的单词有bike cake
  给定一个字符串,以空格为分隔符
  反转每个单词的字母
  若单词中包含如数字等其他非字母时不进行反转
  反转后计算其中含有相对开音节结构的子串个数
  (连续子串中部分字符可以重复)
  
  输入描述
  字符串 以空格分割的多个单词
  长度<10000 字母只考虑小写
  
  输出描述
  含有相对开音节结构的子串个数
  
  示例1:
  输入
  ekam a ekac
  输出
  2
  说明:
  反转后为  make a cake 其中make和cake为相对开音节子串
  返回2
  
  示例2:
  输入
  !ekam a ekekac
  输出
  2
  说明
  反转后为 !ekam a cakeke
  因为!ekam含有非英文字母,所以未反转
  其中 cake和keke 为相对开音节子串 返回2
    // 疑问:不进行反转的单词要不要算相对开音节子串?我这里是算的,如果不算的话,则将反转后的单词单独放到集合里,在进行处理
    // 相对开音节结构的子串个数
    // 解题思路:遍历所有单词,根据条件进行反转,反转后在计算相对开音节结构的子串个数
    public static void test047() {
        Scanner sc = new Scanner(System.in);
        String line = sc.nextLine();
        String[] split = line.split(" ");
        // 相对开音节结构的子串个数
        int count = 0;
        for (int i = 0; i < split.length; i++) {
            String str = split[i];
            // 若单词中包含如数字等其他非字母时不进行反转
            if (str.replaceAll("[a-z]", "").length() == 0) {
                String newStr = "";
                for (int j = 0; j < str.length(); j++) {
                    newStr = str.charAt(j) + newStr;
                }
                str = newStr;
            }

            // 计算相对开音节结构的子串个数
            for (int k = 0; k < str.length() - 3; k++) {
                // 辅音+元音(aeiou)+辅音(r除外)+e
                if (!"aeiou".contains(str.charAt(k) + "")
                        && "aeiou".contains(str.charAt(k + 1) + "")
                        && !"aeiour".contains(str.charAt(k + 2) + "")
                        && 'e' == str.charAt(k + 3)) {
                    count++;
                }
            }
        }
        System.out.println(count);
    }

46.火星人公式求值

  已知火星人使用的运算符号为#;$
  其与地球人的等价公式如下
  x#y=2*x+3*y+4
  x$y=3*x+y+2
  x y是无符号整数
  地球人公式按照c语言规则进行计算
  火星人公式中$符优先级高于# 相同的运算符按从左到右的顺序运算
  
  输入描述:
  火星人字符串表达式结尾不带回车换行
  输入的字符串说明是 字符串为仅有无符号整数和操作符组成的计算表达式
  
  1.用例保证字符串中操作数与操作符之间没有任何分隔符
  2.用例保证操作数取值范围为32位无符号整数,
  3.保证输入以及计算结果不会出现整型溢出
  4.保证输入的字符串为合法的求值报文
  例如: 123#4$5#76$78
  5.保证不会出现非法的求值报文
  例如: #4$5 这种缺少操作数
  4$5#  这种缺少操作数
  4#$5  这种缺少操作数
  4 $5  有空格
  3+4-5*6/7 有其他操作符
  12345678987654321$54321 32位整数溢出
  
  输出描述:
  根据火星人字符串输出计算结果
  结尾不带回车换行
  
  案例1:
  输入:
  7#6$5#12
  输出:
  226
  
  说明 示例7#6$5#12=7#(3*6+5+2)#12
  =7#25#12
  =(2*7+3*25+4)#12
  =93#12
  =2*93+3*12+4
  =226
    // 火星人公式求值
    // 解题思路:根据数字、#$ 将字符串分割成两个数组,先计算$,在计算#
    public static void test046() {
        Scanner sc = new Scanner(System.in);
        String line = sc.nextLine();
        String[] sign = line.split("[0-9]+"); // { ,#,$,$}
        List<String> signList = new ArrayList<>();
        // 数字前面是空串,所以从1开始
        for (int i = 1; i < sign.length; i++) {
            signList.add(sign[i]);
        }
        String[] nums = line.split("[$|#]+"); // {1,2,23,34}
        List<Integer> numsList = new ArrayList();
        for (int i = 0; i < nums.length; i++) {
            numsList.add(Integer.parseInt(nums[i]));
        }

        // 找出所有的$
        while (signList.indexOf("$") != -1) {
            int index$ = signList.indexOf("$");
            // 计算$表达式
            int sum = calculation$(numsList.get(index$), numsList.get(index$ + 1));
            // 替换 $前后的数字 为 $表达式的值 
            numsList.set(index$, sum);
            numsList.remove(index$ + 1);
            // 移除$符号
            signList.remove(index$);
        }
        // 计算#表达式的值
        int res = numsList.get(0);
        for (int i = 1; i < numsList.size(); i++) {
            res = calculation(res, numsList.get(i));
        }
        System.out.println(res);
    }
    
   /**
     * x$y=3*x+y+2
     * @param num1
     * @param num2
     * @return
     */
    private static int calculation$(int num1, int num2) {
        return 3 * num1 + num2 + 2;
    }

    /**
     * x#y=2*x+3*y+4
     * @param num1
     * @param num2
     * @return
     */
    private static int calculation(int num1, int num2) {
        return 2 * num1 + 3 * num2 + 4;
    }

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

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

chenzm666666

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

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

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

打赏作者

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

抵扣说明:

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

余额充值