概述
华为od机试题 真题
- 86.射击比赛成绩排序
- 85.计算屏幕字母数量
- 84.组成最大数字
- 82.输出字符串中最小数字
- 81.数字4的个数
- 80.整数排列
- 79.多条件排列
- 78.时间排序
以下题目附带Java解法,是我个人写的,不一定是标准答案,没有真正的测试数据,只能说是我自己认为通过率100%,也不一定是最优解。如果有错误或是有更好的解法,请评论告诉我!!!
86.射击比赛成绩排序
给定一个射击比赛成绩单
包含多个选手若干次射击的成绩分数
请对每个选手按其最高三个分数之和进行降序排名
输出降序排名后的选手id序列
条件如下
1. 一个选手可以有多个射击成绩的分数,且次序不固定
2. 如果一个选手成绩少于3个,则认为选手的所有成绩无效,排名忽略该选手
3. 如果选手的成绩之和相等,则相等的选手按照其id降序排列
输入描述:
输入第一行
一个整数N
表示该场比赛总共进行了N次射击
产生N个成绩分数
2<=N<=100
输入第二行
一个长度为N整数序列
表示参与每次射击的选手id
0<=id<=99
输入第三行
一个长度为N整数序列
表示参与每次射击选手对应的成绩
0<=成绩<=100
输出描述:
符合题设条件的降序排名后的选手ID序列
示例一
输入:
13
3,3,7,4,4,4,4,7,7,3,5,5,5
53,80,68,24,39,76,66,16,100,55,53,80,55
输出:
5,3,7,4
说明:
该场射击比赛进行了13次
参赛的选手为{3,4,5,7}
3号选手成绩53,80,55 最高三个成绩的和为188
4号选手成绩24,39,76,66
最高三个成绩的和为181
5号选手成绩53,80,55
最高三个成绩的和为188
7号选手成绩68,16,100
最高三个成绩的和为184
比较各个选手最高3个成绩的和
有3号=5号>7号>4号
由于3号和5号成绩相等
且id 5>3
所以输出5,3,7,4
// 射击比赛成绩排序
public static void test086() {
Scanner sc = new Scanner(System.in);
String line1 = sc.nextLine();
String line2 = sc.nextLine();
String line3 = sc.nextLine();
String[] strings2 = line2.split(",");
String[] strings3 = line3.split(",");
// 用Map存储,key存选手号,value用list存选手所有的成绩
Map<Integer, List<Integer>> map = new HashMap<>();
for (int i = 0; i < Integer.parseInt(line1); i++) {
if (map.containsKey(Integer.parseInt(strings2[i]))) {
List<Integer> list = map.get(Integer.parseInt(strings2[i]));
list.add(Integer.parseInt(strings3[i]));
} else {
List<Integer> list = new ArrayList<>();
list.add(Integer.parseInt(strings3[i]));
map.put(Integer.parseInt(strings2[i]), list);
}
}
Map<Integer, Integer> map2 = new HashMap();
// 遍历Map,对选手成绩进行筛选,用一个Map<Integer, Integer>来存选手号和最大总成绩
for (Integer key : map.keySet()) {
List<Integer> list = map.get(key);
int listSize = list.size();
if (listSize >= 3) {
Collections.sort(list);
// 最大总成绩
int listAll = list.get(listSize - 1) + list.get(listSize - 2) + list.get(listSize - 3);
map2.put(key, listAll);
}
}
// 用于拼接输出结果
StringBuilder builder = new StringBuilder();
// 通过stream流的形式进行排序
sorted:对集合进行排序
e1与e2比较,结果大于0互换位置 小于等于0不变
Set<Map.Entry<Integer, Integer>> entries = map2.entrySet();
entries.stream().sorted((e1, e2) -> {
if (e1.getValue().equals(e2.getValue())) {
// 分数相等,选手号大的在前
return e2.getKey() - e1.getKey();
} else {
// 分数大的在前
return e2.getValue() - e1.getValue();
}
}).forEach((e) -> {
builder.append(e.getKey() + ",");
});
System.out.println(builder.substring(0, builder.length() - 1));
}
85.计算屏幕字母数量
有一个特殊的五键键盘
上面有A、Ctrl-C、Ctrl-X、Ctrl-V、Ctrl-A
A键在屏幕上输出一个字母A
Ctrl-C将当前所选的字母复制到剪贴板
Ctrl-X将当前选择的字母复制到剪贴板并清空所选择的字母
Ctrl-V将当前剪贴板的字母输出到屏幕
Ctrl-A选择当前屏幕中所有字母
注意:
1. 剪贴板初始为空
2. 新的内容复制到剪贴板会覆盖原有内容
3. 当屏幕中没有字母时,Ctrl-A无效
4. 当没有选择字母时Ctrl-C、Ctrl-X无效
5. 当有字母被选择时A和Ctrl-V这两个输出功能的键,
会先清空所选的字母再进行输出
给定一系列键盘输入,
输出最终屏幕上字母的数量
输入描述:
输入为一行
为简化解析用数字12345分别代替A、Ctrl-C、Ctrl-X、Ctrl-V、Ctrl-A的输入
数字用空格分割
输出描述:
输出一个数字为屏幕上字母的总数量
示例一:
输入:
1 1 1
输出:
3
示例二:
输入:
1 1 5 1 5 2 4 4
输出:
2
// 计算屏幕字母数量
public static void test085() {
Scanner sc = new Scanner(System.in);
String line = sc.nextLine();
String[] split = line.split(" ");
// 屏幕内容
int result = 0;
// 剪切板内容
int ctrl_c_x = 0;
// ctrl_A选中的内容
int ctrl_a = 0;
for (int i = 0; i < split.length; i++) {
if (1 == Integer.parseInt(split[i])) { // A
// Ctrl-A 选中内容,输入A则覆盖,屏幕内容长度为1
if (ctrl_a != 0) {
result = 1;
} else { // Ctrl-A 没选中内容,输入A屏幕内容长度加1
result++;
}
ctrl_a = 0;
} else if (2 == Integer.parseInt(split[i])) { // Ctrl-C
// 当Ctrl-A 选中内容时,Ctrl-C才有效
if (0 != ctrl_a) {
// 剪切板内容等于ctrl_A选中的内容
ctrl_c_x = ctrl_a;
}
} else if (3 == Integer.parseInt(split[i])) { // Ctrl-X
// 当Ctrl-A 选中内容时,Ctrl-X才有效
if (0 != ctrl_a) {
// 剪切板内容等于ctrl_A选中的内容
ctrl_c_x = ctrl_a;
// Ctrl-X后屏幕内容长度为0
result = 0;
// Ctrl-X后ctrl_A选中内容长度为0
ctrl_a = 0;
}
} else if (4 == Integer.parseInt(split[i])) { // Ctrl-V
// 当剪切板有内容ctrl_v才有用
// PS:这里有个疑问:当剪切板为空时,使用Ctrl-V是用空覆盖还是无效呢??我的处理是无效,我觉得这里题目描述的不是很清楚
if (0 != ctrl_c_x) {
// Ctrl-A 选中内容时
if (ctrl_a != 0) {
result = ctrl_c_x;
ctrl_a = 0;
} else if (ctrl_a == 0) { // Ctrl-A 没选中内容时
result += ctrl_c_x;
}
}
} else if (5 == Integer.parseInt(split[i])) { // Ctrl-A
// 选中屏幕所有内容
ctrl_a = result;
}
}
System.out.println(result);
}
84.组成最大数字
小组中每位都有一张卡片
卡片是6位以内的正整数
将卡片连起来可以组成多种数字
计算组成的最大数字
输入描述:
","分割的多个正整数字符串
不需要考虑非数字异常情况
小组种最多25个人
输出描述:
最大数字字符串
示例一
输入
22,221
输出
22221
示例二
输入
4589,101,41425,9999
输出
9999458941425101
// 组成最大数字
public static void test0843() {
Scanner sc = new Scanner(System.in);
String line = sc.nextLine();
String[] split = line.split(",");
// 类似于冒泡排序,用双层for循环,将最大的组合往前放
for (int i = 0; i < split.length - 1; i++) {
for (int j = i + 1; j < split.length; j++) {
String res1 = split[i] + split[j];
String res2 = split[j] + split[i];
if (Integer.parseInt(res1) < Integer.parseInt(res2)) {
String value = split[i];
split[i] = split[j];
split[j] = value;
}
}
}
for (int i = 0; i < split.length; i++) {
System.out.print(split[i]);
}
}
82.输出字符串中最小数字
1.输入字符串s输出s中包含所有整数的最小和,
说明:1字符串s只包含a~z,A~Z,+,-,
2.合法的整数包括正整数,一个或者多个0-9组成,如:0,2,3,002,102
3.负整数,负号开头,数字部分由一个或者多个0-9组成,如-2,-012,-23,-00023
输入描述:包含数字的字符串
输出描述:所有整数的最小和
示例:
输入:
bb1234aa
输出
10
输入:
bb12-34aa
输出:
-31
说明:1+2-(34)=-31
// 输出字符串中最小数字
public static void test082() {
Scanner sc = new Scanner(System.in);
String line = sc.nextLine();
// 将字符串转为字符数组
char[] chars = line.toCharArray();
// 累加结果
int sum = 0;
for (int i = 0; i < chars.length; i++) {
char c = chars[i];
if (c == '-') {
int start = i;
i++;
while (i < chars.length && Character.isDigit(chars[i])) {
i++;
}
// 截取负数
String substring = line.substring(start, i);
// 当substring = 1时只有一个负号
if (substring.length() > 1) {
sum += Integer.parseInt(substring);
}
}
// 判断字符是不是数字
if (Character.isDigit(c)) {
// 将字符数字转为数字,当字符数字小于第二个参数时,返回-1
sum += Character.digit(c, 10);
}
}
System.out.println(sum);
}
81.数字4的个数
程序员小明打了一辆出租车去上班。出于职业敏感,他注意到这辆出租车的计费表有点问题,总是偏大。
出租车司机解释说他不喜欢数字4,所以改装了计费表,任何数字位置遇到数字4就直接跳过,其余功能都正常。
比如:
1. 23再多一块钱就变为25;
2. 39再多一块钱变为50;
3. 399再多一块钱变为500;
小明识破了司机的伎俩,准备利用自己的学识打败司机的阴谋。
给出计费表的表面读数,返回实际产生的费用。
输入描述:
只有一行,数字N,表示里程表的读数。
(1<=N<=888888888)。
输出描述:
一个数字,表示实际产生的费用。以回车结束。
示例1:
输入
5
输出
4
说明
5表示计费表的表面读数。
表示实际产生的费用其实只有4块钱。
示例2:
输入
17
输出
15
说明
17表示计费表的表面读数。
15表示实际产生的费用其实只有15块钱。
示例3:
输入
100
输出
81
说明:100表示计费表的表面读数,81表示实际产生的费用其实只有81块钱
// 数字4的个数
public static void test081(){
Scanner sc = new Scanner(System.in);
int start = sc.nextInt();
// 数字中有4的个数
int sum = 0;
for (int i = 1; i <= start; i++) {
// 将数字转为字符串,判断数字是否包含4
if ((i+"").contains("4")) {
// 累加
sum++;
}
}
System.out.println(start - sum);
80.整数排列
给定参数n,从1到n会有n个整数:1,2,3,...,n,
这n个数字共有n!种排列.
按大小顺序升序列出所有排列的情况,并一一标记,
当n=3时,所有排列如下:
"123" "132" "213" "231" "312" "321"
给定n和k,返回第k个排列.
输入描述:
输入两行,第一行为n,第二行为k,
给定n的范围是[1,9],给定k的范围是[1,n!]。
输出描述:
输出排在第k位置的数字。
实例1:
输入:
3
3
输出:
213
说明
3的排列有123,132,213...,那么第三位置就是213
实例2:
输入
2
2
输出:
21
说明
2的排列有12,21,那么第二位置的为21
// 整数排列
这道题目前还不懂,稍后总结
public static void test080(){
Scanner in = new Scanner(System.in);
int n = Integer.parseInt(in.nextLine());
int k = Integer.parseInt(in.nextLine());
StringBuilder sb = new StringBuilder();
List<Integer> candidates = new ArrayList<>();
int[] factorials = new int[n + 1];
factorials[0] = 1;
int fact = 1;
for (int i = 1; i <= n; ++i) {
candidates.add(i);
fact *= i;
factorials[i] = fact;
}
k -= 1;
for (int i = n - 1; i >= 0; --i) {
// 计算候选数字的index
int index = k / factorials[i];
sb.append(candidates.remove(index));
k -= index * factorials[i];
}
System.out.println(sb);
}
79.多条件排列
某学校举行运动会,学生们按编号(1、2、3.....n)进行标识,
现需要按照身高由低到高排列,
对身高相同的人,按体重由轻到重排列,
对于身高体重都相同的人,维持原有的编号顺序关系。
请输出排列后的学生编号
输入描述:
两个序列,每个序列由N个正整数组成,(0<n<=100)。
第一个序列中的数值代表身高,第二个序列中的数值代表体重,
输出描述:
排列结果,每个数据都是原始序列中的学生编号,编号从1开始,
实例一:
输入:
4
100 100 120 130
40 30 60 50
输出:
2134
// 多条件排列
public static void test079() {
Scanner sc = new Scanner(System.in);
int len = Integer.parseInt(sc.nextLine());
// 身高
String line1 = sc.nextLine();
// 体重
String line2 = sc.nextLine();
String[] split1 = line1.split(" ");
String[] split2 = line2.split(" ");
// map的key为编号,value为学生的身高、体重组成的list
Map<Integer, List<Integer>> map = new HashMap<>();
for (int i = 1; i <= len; i++) {
List<Integer> list = new ArrayList<>();
// 身高
list.add(Integer.parseInt(split1[i - 1]));
// 体重
list.add(Integer.parseInt(split2[i - 1]));
map.put(i, list);
}
Set<Map.Entry<Integer, List<Integer>>> entrySet = map.entrySet();
// 通过stream流的形式进行排序
sorted:对集合进行排序
s1与s2比较,结果大于0互换位置 小于等于0不变
entrySet.stream().sorted((s1, s2) -> {
List<Integer> value1 = s1.getValue();
List<Integer> value2 = s2.getValue();
// 身高相等比体重
return value1.get(0) == value2.get(0) ? value1.get(1) - value2.get(1) : value1.get(0) - value2.get(0);
}).forEach((s) -> {
System.out.print(s.getKey());
});
}
78.时间排序
运维工程师采集到某产品线网运行一天产生的日志n条
现需根据日志时间先后顺序对日志进行排序
日志时间格式为H:M:S.N
H表示小时(0~23)
M表示分钟(0~59)
S表示秒(0~59)
N表示毫秒(0~999)
时间可能并没有补全
也就是说
01:01:01.001也可能表示为1:1:1.1
输入描述
第一行输入一个整数n表示日志条数
1<=n<=100000
接下来n行输入n个时间
输出描述
按时间升序排序之后的时间
如果有两个时间表示的时间相同
则保持输入顺序
示例:
输入:
2
01:41:8.9
1:1:09.211
输出
1:1:09.211
01:41:8.9
示例
输入
3
23:41:08.023
1:1:09.211
08:01:22.0
输出
1:1:09.211
08:01:22.0
23:41:08.023
示例
输入
2
22:41:08.023
22:41:08.23
输出
22:41:08.023
22:41:08.23
时间相同保持输入顺序
// 时间排序
public static void test078() {
Scanner sc = new Scanner(System.in);
// 输入的个数
int len = Integer.parseInt(sc.nextLine());
List<String> list = new ArrayList<>();
int i = 0;
while (i < len) {
list.add(sc.nextLine());
i++;
}
sc.close();
// 对集合进行排序
a1与a2比较,结果大于0互换位置 小于等于0不变
list.stream().sorted((a1, a2) -> {
// 根据规则切分出时 分 秒 毫秒
String[] time1 = a1.split(":");
String[] time2 = a2.split(":");
// 用.进行分割时需要用到转义字符 \
String[] s_n1 = time1[2].split("\.");
String[] s_n2 = time2[2].split("\.");
int h1 = Integer.parseInt(time1[0]);
int h2 = Integer.parseInt(time2[0]);
int m1 = Integer.parseInt(time1[1]);
int m2 = Integer.parseInt(time2[1]);
int s1 = Integer.parseInt(s_n1[0]);
int s2 = Integer.parseInt(s_n2[0]);
int n1 = Integer.parseInt(s_n1[1]);
int n2 = Integer.parseInt(s_n2[1]);
// 小时不相等比较小时
if (h1 != h2) {
return h1 - h2;
}
// 分钟不相等比较分钟
if (m1 != m2) {
return m1 - m2;
}
// 秒不相等比较秒
if (s1 != s2) {
return s1 - s2;
}
// 毫秒不相等比较毫秒
if (n1 != n2) {
return n1 - n2;
}
// 都相等按原来顺序
return 0;
}).forEach((a) -> {
System.out.println(a);
});
}
更多华为od机试题请点这里<华为od机试题2 真题>,每篇8题,有更多的题也请告诉我啊
最后
以上就是秀丽白云为你收集整理的华为od机试题1 真题的全部内容,希望文章能够帮你解决华为od机试题1 真题所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复