华为OD机试题(不间断更新)
Posted Mr. Dreamer Z
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了华为OD机试题(不间断更新)相关的知识,希望对你有一定的参考价值。
目录
这些代码都未进行优化,只是为了记录对应题目以及做个总结,是基于思路去写的。有更好方式的童鞋请告知,后续会抽出时间进行代码优化
第一题:字符串消消乐
字符串消消乐。相邻且相同的字符串可以消除,消除后字符继续消除,给你一串字符,给出最终的长度。字符串大小写敏感,有其他非字母字符返回0。
例如,在 "abbaca" 中,我们可以删除 "bb" 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。
之后我们得到字符串 "aaca",其中又只有 "aa" 可以执行重复项删除操作,所以最后的字符串为 "ca"。
这道题其实比较简单了,我们只需要判断相邻的两个字符是否是一致的。如果一致,那么将其排除掉,重新组装字符串。如果不一致,那么下标往后移动
public static void main(String[] args)
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext())
String str = scanner.nextLine();
String str1 = str.replaceAll("[^a-zA-Z]", "");
if (str1.length() != str.length())
System.out.println(0);
System.out.println(getVal(str, 0));
private static String getVal(String str, int i)
// 如果i==str.length
if (i == str.length() - 1 || "".equals(str))
return str;
if (str.charAt(i) == str.charAt(i + 1))
// 如果相同,那么直接消除
String sub1 = str.substring(0, i);
String sub2 = str.substring(i + 1 + 1);
str = sub1 + sub2;
// 从头开始
i = 0;
else
// i+1继续寻找
i = i + 1;
return getVal(str, i);
这道题的关键点在于,避免处理非字符的数据以及如何组装字符串,还有如果消除相同字符之后,下标从头开始。
第二题,We Are A Team
【We Are A Team】
总共有 n 个人在机房,每个人有一个标号(1<=标号<=n),他们分成了多个团队,需要你根据收到的 m 条消息判定指定的两个人是否在一个团队中,具体的:
1、消息构成为 a b c,整数 a、b 分别代表两个人的标号,整数 c 代表指令
2、c == 0 代表 a 和 b 在一个团队内
3、c == 1 代表需要判定 a 和 b 的关系,如果 a 和 b 是一个团队,输出一行’we are a team’,如果不是,输出一行’we are not a team’
4、c 为其他值,或当前行 a 或 b 超出 1~n 的范围,输出‘da pian zi’
输入描述
第一行包含两个整数 n,m(1<=n,m<100000),分别表示有 n 个人和 m 条消息
随后的 m 行,每行一条消息,消息格式为:a b c(1<=a,b<=n,0<=c<=1)
输出描述: 1、c ==1,根据 a 和 b 是否在一个团队中输出一行字符串,在一个团队中输出‘we are a team’,不在一个团队中输出’we are not a team’ 2、c 为其他值,或当前行 a 或 b 的标号小于 1 或者大于 n 时,输出字符串‘da pian zi’
如果第一行 n 和 m 的值超出约定的范围时,输出字符串”Null”。
示例1 输入输出示例仅供调试,后台判题数据一般不包含示例
输入
5 7
1 2 0
4 5 0
2 3 0
1 2 1
2 3 1
4 5 1
1 5 1
输出
We are a team
We are a team
We are a team
We are not a team
示例2 输入输出示例仅供调试,后台判题数据一般不包含示例
输入
5 6
1 2 0
1 2 1
1 5 0
2 3 1
2 5 1
1 3 2
输出
we are a team
we are not a team
we are a team
da pian zi
说实话,我最讨厌这种描述臭又长,得花大量时间去审题,找规则,试错的题。特别是在考试的时候~
这道题其实也还好,我们首先要弄清楚a,b,c这三个的含义,a和b代表人员标号,c代表是否在一个团队。而且这道题首先会由输入告知你一部分所属一个团队的人员。
我们可以创建两个集合,一个集合来收集所属同一团队的人员信息,第二个集合来收集我们需要去输出的人员信息。但是这其中有一个难点,就是说我们要根据给出的信息去推演出所属一个团队的人员。比如说:1 2 0 、2 3 0 ,那么我们则可以得知,1和3是在同一个团队中。那么将其算出,加入我们的第一个集合中。或者1 2 0 和 1 5 0,那么我们也要得出2和5是所属与同一个团队中。
public class Test05
public static void main(String[] args)
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext())
int n = scanner.nextInt();
int m = scanner.nextInt();
// 输入
List<Team> list = new ArrayList<>();
List<Team> sendList = new ArrayList<>();
for (int i = 0; i < m; i++)
int a = scanner.nextInt();
int b = scanner.nextInt();
int c = scanner.nextInt();
if (c == 0)
list.add(new Team(a, b, c));
else
sendList.add(new Team(a, b, c));
List<Team> teamList = getList(list);
for (Team team : sendList)
if ((team.c != 0 && team.c != 1) || Math.min(team.a, team.b) < 1 || Math.max(team.a, team.b) > n)
System.out.println("da pian zi");
continue;
if (team.c == 1)
// 判断是否在之前的集合中存在
List<Team> collect = teamList.stream().filter(val -> val.getA() == team.a && val.getB() == team.b).collect(Collectors.toList());
if (collect != null && collect.size() > 0)
System.out.println("we are a team");
else
System.out.println("we are not a team");
private static List<Team> getList(List<Team> list)
// 当加入数据时,需要判断1,2 2,3 -> 1,3 这种推演
List<Team> newList = new ArrayList<>();
for (int i = 0; i < list.size() - 1; i++)
for (int j = i + 1; j < list.size(); j++)
Team team1 = list.get(i);
Team team2 = list.get(j);
// 由于都是0,那么代表是一个团队
if (team1.b == team2.a)
// 那么将team1.a 和 team2.b进行组合
newList.add(new Team(team1.a, team2.b, 0));
else if (team1.a == team2.a)
newList.add(new Team(team1.b, team2.b, 0));
else if (team1.a == team2.b)
newList.add(new Team(team1.b, team2.a, 0));
// 将两个集合组装
list.addAll(newList);
return list;
class Team
int a;
int b;
int c;
public int getA()
return a;
public int getB()
return b;
public Team(int a, int b, int c)
this.a = a;
this.b = b;
this.c = c;
这道题的关键点:1.审题(去理解清楚这种臭又长描述的题的具体信息,一般来说这种题都比较简单,如果理解清楚容易做出来) 2.需要自己去推演出处于同一个团队的人员
第三题 求剩余扑克牌最大顺子问题
扑克牌为 345678910JQKA 每种牌4张
输入是你现在的手牌, 还有已经打出去的牌
求剩下的牌中能凑出来的最大的顺子是多少
这里顺子的大小优先比较长度, 相同长度的顺子则比较牌面大小
比如:
你的手牌 3-3-3-8-8-8-8
已经打出的牌 4-4-5-5-6-6
最大的顺子是 9-10-J-Q-K-A
这道题和牛客网华为算法题HJ88差不多,是同类型题。
首先审题,由题可知,有3-A每种4张牌,我们手里有牌,打出去有牌,剩下的还有牌
输入时,我们就可以得知手中牌和打出去的牌。
第一步,我们先将所有的牌得到。
第二步,将手中的牌和打出去的牌过滤掉
第三步,遍历所有的牌,开始组合,如果遇到还剩0张牌的牌,那么保存当前组合的数据,跳过当前牌,往下继续组合
public static void main(String[] args)
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext())
// 手牌
String str1 = scanner.nextLine();
// 打出的牌
String str2 = scanner.nextLine();
// 先得到总的牌
LinkedHashMap<String, Integer> linkedHashMap = new LinkedHashMap<>();
for (int i = 3; i <= 10; i++)
linkedHashMap.put(i + "", 4);
linkedHashMap.put("J", 4);
linkedHashMap.put("Q", 4);
linkedHashMap.put("K", 4);
linkedHashMap.put("A", 4);
// 将剩下的牌得到
String[] arr1 = str1.split("-");
for (int i = 0; i < arr1.length; i++)
String key = arr1[i];
linkedHashMap.put(key, linkedHashMap.get(key) - 1);
String[] arr2 = str2.split("-");
for (int i = 0; i < arr2.length; i++)
String key = arr2[i];
linkedHashMap.put(key, linkedHashMap.get(key) - 1);
// 得到剩下的牌
Set<String> keySet = linkedHashMap.keySet();
List<String> list = getList(keySet, linkedHashMap);
// 得到最长的,如果有相同的,那么取下一个
int max = 0;
String res = "";
for (String str : list)
String[] subArr = str.split("-");
if (subArr.length >= max)
max = subArr.length;
res = str;
System.out.println(res);
private static List<String> getList(Set<String> keySet, LinkedHashMap<String, Integer> linkedHashMap)
String res = "";
List<String> list = new ArrayList<>();
int idx = 0;
boolean flag = false;
for (String key : keySet)
idx++;
if (linkedHashMap.get(key) <= 0)
if (idx == keySet.size())
// 如果是最后一位,那么说明都已经放入集合中
flag = true;
if(!"".equals(res))
// 如果遇到是val是0的key,那么自动组装放入集合
list.add(res.substring(0, res.length() - 1));
// 重新赋值
res = new String();
continue;
else
res += key + "-";
// 如果flag为false,那么说明最后一位未放入集合中
if (idx == keySet.size() && !flag)
list.add(res.substring(0, res.length() - 1));
return list;
这道题的难点其实就是如何组装数据,组装数据我们需要注意一下几点:
1.如何遇到该类牌的数量为0,那么将其之前的组合记录,然后跳过当前类型牌
2.头尾牌为0时,需要特殊处理。如果头牌0,注意下标问题。如果尾牌不是0,那么需要将当次组装的数据全部放入集合中
第四题 一系列正整数, 从中取三个数拼接后的最小数字
给你一系列数字, 从中取出三个数字, 如果给的数字不到三个有几个取几个
求这几个数字拼接后的最小数字是多少。
比如:
给定 18,123,22,5,12,34,23,43,344,21
拼接后的最小数字是 12,18,5的拼接, 12185
这道题比较简单,我们只需要考虑当前给定的数字是否大于3个以及找出最小的三个进行组装即可
public static void main(String[] args)
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext())
String str = scanner.nextLine();
String[] numArr = str.split(",");
int[] arr = new int[numArr.length];
for (int i = 0; i < numArr.length; i++)
arr[i] = Integer.valueOf(numArr[i]);
Arrays.sort(arr);
List<Integer> list = new ArrayList<>();
if (numArr.length < 3)
for (int i = 0; i < arr.length; i++)
list.add(arr[i]);
else
for (int i = 0; i < 3; i++)
list.add(arr[i]);
// 组合起来之后求最小值
String[] s = new String[list.size()];
for (int i = 0; i < list.size(); i++)
s[i] = list.get(i) + "";
Arrays.sort(s, ((o1, o2) -> (o1 + o2).compareTo(o2 + o1)));
StringBuilder sb = new StringBuilder();
for (String st : s)
sb.append(st);
System.out.println(sb);
关键点就是如何找到最小的组合,通过compareTo()进行组合得到最下的组合数据
以上是关于华为OD机试题(不间断更新)的主要内容,如果未能解决你的问题,请参考以下文章
华为OD机试题 - 最近的点(JavaScript)| 含思路
华为OD机试题 - 最小叶子节点(JavaScript)| 含思路
华为OD机试题 - 寻找路径(JavaScript)| 机考必刷
华为OD机试题 - 不等式(JavaScript)| 含思路