以下题目附带Java解法,是我个人写的,不一定是标准答案,没有真正的测试数据,只能说是我自己认为通过率100%,也不一定是最优解。如果有错误或是有更好的解法,请评论告诉我!!!
67.最小字符串
题目描述:
给定一个字符串s,最多只能进行一次变换,返回变换后能得到的最小字符串(按照字典序进行比较)。
变换规则:交换字符串中任意两个不同位置的字符。
输入描述:
一串小写字母组成的字符串s。
输出描述:
按照要求进行变换得到的最小字符串。
备注:
s是都是小写字符组成
1<=s.length<=1000
示例
输入:abcdef
输出:abcdef
说明:abcdef已经是最小字符串,不需要交换
输入:bcdefa
输出:acdefb
说明:a和b进行位置交换,可以得到最小字符串
// 最小字符串
// 解题思路:遍历每一个元素,找到最小的,与第一个元素交换,如果第一个元素是最小的,则找第二个元素与第二小的元素交换,以此类推
public static void test067() {
Scanner sc = new Scanner(System.in);
String line = sc.nextLine();
char[] chars = line.toCharArray();
// 遍历每一个元素
for (int j = 0; j < chars.length; j++) {
// 存放最小的元素
char minValue = chars[j];
// 存放最小元素的索引
int minIndex = j;
// 遍历往后的所有元素
for (int i = j + 1; i < chars.length; i++) {
// 使用<=是因为要拿到排在最后的最小元素
if (chars[i] <= minValue) {
minValue = chars[i];
minIndex = i;
}
}
// 当最小元素不是第一个时,则交换第一个元素与最小元素的位置,输出后结束
if (minIndex != j && chars[j] != chars[minIndex]) {
chars[minIndex] = chars[j];
chars[j] = minValue;
System.out.println(new String(chars));
return;
}
}
// 当元素是按顺序排的,则直接输出
System.out.println(line);
}
66.最长元音字符串
定义当一个字符串只有元音字母(a,e,i,o,u,A,E,I,O,U)组成,
称为元音字符串,现给定一个字符串,请找出其中最长的元音字符串,
并返回其长度,如果找不到请返回0,
字符串中任意一个连续字符组成的子序列称为该字符串的子串
<p>
输入描述:
一个字符串其长度 0<length ,字符串仅由字符a-z或A-Z组成
输出描述:
一个整数,表示最长的元音字符子串的长度
<p>
示例1:
输入
asdbuiodevauufgh
输出
3
说明:
最长的元音字符子串为uio和auu长度都为3,因此输出3
// 最长元音字符串
// 解题思路:定义一个元音字符数组,判断字符是否在数组中,且是连续的,定义一个临时长度来记录连续且元音字符长度,保留最长的
public static void test066() {
Scanner sc = new Scanner(System.in);
char[] chars = sc.nextLine().toCharArray();
List<Character> list = new ArrayList<>();
list.add('a');
list.add('e');
list.add('i');
list.add('o');
list.add('u');
list.add('A');
list.add('E');
list.add('I');
list.add('O');
list.add('U');
// 最大长度
int maxLen = 0;
// 临时长度
int tempLen = 0;
for (int i = 0; i < chars.length; i++) {
// 元音且连续
while (i < chars.length && list.contains(chars[i])) {
i++;
tempLen++;
}
// 保留最长串
maxLen = Math.max(maxLen, tempLen);
// 初始化
tempLen = 0;
}
System.out.println(maxLen);
}
65.字母所在字符串中的位置索引
输入一个由N个大小写字母组成的字符串
按照ASCII码值从小到大进行排序
查找字符串中第K个最小ASCII码值的字母(k>=1)
输出该字母所在字符串中的位置索引(字符串的第一个位置索引为0)
k如果大于字符串长度则输出最大ASCII码值的字母所在字符串的位置索引
如果有重复字母则输出字母的最小位置索引
输入描述
第一行输入一个由大小写字母组成的字符串
第二行输入k k必须大于0 k可以大于输入字符串的长度
输出描述
输出字符串中第k个最小ASCII码值的字母所在字符串的位置索引
k如果大于字符串长度则输出最大ASCII码值的字母所在字符串的位置索引
如果第k个最小ASCII码值的字母存在重复 则输出该字母的最小位置索引
示例一
输入
AbCdeFG
3
输出
5
说明
根据ASCII码值排序,第三个ASCII码值的字母为F
F在字符串中位置索引为5(0为字符串的第一个字母位置索引)
示例二
输入
fAdDAkBbBq
4
输出
6
说明
根据ASCII码值排序前4个字母为AABB由于B重复则只取B的第一个最小位置索引6
而不是第二个B的位置索引8
// 字母所在字符串中的位置索引
// 解题思路:将字符串转为集合,对集合进行排序,找到指定位置的值,在字符串中找该字符所在位置索引
public static void test065() {
Scanner sc = new Scanner(System.in);
String line = sc.nextLine();
char[] chars = line.toCharArray();
int index = sc.nextInt();
int length = chars.length;
List<Character> list = new ArrayList<>();
for (int i = 0; i < length; i++) {
list.add(chars[i]);
}
// 对集合进行排序
Collections.sort(list);
// 大于字符长度
if (index > length) {
// 输出排序后最后一个字符所在字符串的索引位置
System.out.println(line.indexOf(list.get(length - 1)));
} else {
// 输出指定位置字符所在字符串的索引位置
System.out.println(line.indexOf(list.get(index - 1)));
}
}
64.计算图形面积
绘图机器的绘图笔初始位置在原点(0,0)
机器启动后按照以下规则来进行绘制直线
1. 尝试沿着横线坐标正向绘制直线
直到给定的终点E
2. 期间可以通过指令在纵坐标轴方向进行偏移
offsetY为正数表示正向偏移,为负数表示负向偏移
给定的横坐标终点值E 以及若干条绘制指令
请计算绘制的直线和横坐标轴以及x=E的直线组成的图形面积
输入描述:
首行为两个整数N 和 E
表示有N条指令,机器运行的横坐标终点值E
接下来N行 每行两个整数表示一条绘制指令x offsetY
用例保证横坐标x以递增排序的方式出现
且不会出现相同横坐标x
取值范围:
0<N<=10000
0<=x<=E<=20000
-10000<=offsetY<=10000
输出描述:
一个整数表示计算得到的面积 用例保证结果范围在0到4294967295之内
示例1:
输入:
4 10
1 1
2 1
3 1
4 -2
输出:
12
示例2:
输入:
2 4
0 1
2 -2
输出:
4
// 这个通过率好像只有95%,没有具体的测试数据,我也不知道哪里有问题
// 计算图形面积
// 解题思路:每个点的面积等于下一个点x值 - 当前点x值 乘以 当前点y的累计值。最后一个点则是:终点x值 - 当前点x值 乘以 当前点y的累计值
public static void test064() {
Scanner sc = new Scanner(System.in);
String line1 = sc.nextLine();
String[] split1 = line1.split(" ");
int num = Integer.parseInt(split1[0]);
int end = Integer.parseInt(split1[1]);
// 存放x坐标的值
List<Integer> listX = new ArrayList<>();
// 存放y坐标的值
List<Integer> listY = new ArrayList<>();
for (int i = 0; i < num; i++) {
String line = sc.nextLine();
String[] split = line.split(" ");
listX.add(Integer.parseInt(split[0]));
listY.add(Integer.parseInt(split[1]));
}
// y的累计值
int sumY = 0;
// 总面积
int sumArea = 0;
for (int i = 0; i < num; i++) {
// 最后一个点
if (i == num - 1) {
// y的累计值
sumY += listY.get(i);
// 终点x值 - 当前点x值 乘以 当前点y的累计值
sumArea += (end - listX.get(i)) * Math.abs(sumY);
} else {
// y的累计值
sumY += listY.get(i);
// 下一个点x值 - 当前点x值 乘以 当前点y的累计值
sumArea += (listX.get(i + 1) - listX.get(i)) * Math.abs(sumY);
}
}
System.out.println(sumArea);
}
63.剩余可用字符集
给定两个字符集合
一个是全量字符集
一个是已占用字符集
已占用字符集中的字符不能再使用
要求输出剩余可用字符集
输入描述
1. 输入一个字符串 一定包含@
@前为全量字符集 @后的为已占用字符集
2. 已占用字符集中的字符
一定是全量字符集中的字符
字符集中的字符跟字符之间使用英文逗号隔开
3. 每个字符都表示为字符+数字的形式
用英文冒号分隔
比如a:1标识一个a字符
4. 字符只考虑英文字母,区分大小写
数字只考虑正整型 不超过100
5. 如果一个字符都没被占用 @标识仍存在
例如 a:3,b:5,c:2@
输出描述:
输出可用字符集
不同的输出字符集之间用回车换行
注意 输出的字符顺序要跟输入的一致
不能输出b:3,a:2,c:2
如果某个字符已全部占用 则不需要再输出
示例一:
输入
a:3,b:5,c:2@a:1,b:2
输出
a:2,b:3,c:2
说明:
全量字符集为三个a,5个b,2个c
已占用字符集为1个a,2个b
由于已占用字符不能再使用
因此剩余可用字符为2个a,3个b,2个c
因此输出a:2,b:3,c:2
// 如果全量字符中有重复的,是相加还是取最后一个?? 我做的是相加,如果取最后一个则先remove,在put,就能保证插入顺序
// 剩余可用字符集
// 解题思路:使用按插入顺序排列的LinkedHashMap来存储全量字符集,在减掉已用字符集
public static void test063() {
Scanner sc = new Scanner(System.in);
String line = sc.nextLine();
String[] split = line.split("@");
// 一个字符都没被占用
if (line.charAt(line.length() - 1) == '@') {
System.out.println(line.substring(0, line.length() - 1));
return;
}
String[] allString = split[0].split(",");
String[] userString = split[1].split(",");
// LinkedHashMap 按插入顺序排列
Map<String, Integer> map = new LinkedHashMap<>();
// 遍历全量字符串,存进LinkedHashMap中
for (int i = 0; i < allString.length; i++) {
String[] strAndNum = allString[i].split(":");
String str = strAndNum[0];
int num = Integer.parseInt(strAndNum[1]);
if (map.containsKey(str)) {
map.put(str, map.get(str) + num);
} else {
map.put(str, num);
}
}
// 遍历用过的字符串,在LinkedHashMap中减掉使用的次数
for (int i = 0; i < userString.length; i++) {
String[] strAndNum = userString[i].split(":");
String str = strAndNum[0];
int num = Integer.parseInt(strAndNum[1]);
map.put(str, map.get(str) - num);
}
// 拼接输出的字符串
StringBuilder sb = new StringBuilder();
for (String s : map.keySet()) {
// 只输出有剩余的字符串
if (map.get(s) > 0) {
sb.append(s + ":" + map.get(s) + ",");
}
}
System.out.println(sb.substring(0, sb.length() - 1));
}
62.字符串解压缩
有一种简易压缩算法:针对全部为小写英文字母组成的字符串,
将其中连续超过两个相同字母的部分压缩为连续个数加该字母
其他部分保持原样不变.
例如字符串aaabbccccd 经过压缩变成字符串 3abb4cd
请您编写解压函数,根据输入的字符串,
判断其是否为合法压缩过的字符串
若输入合法则输出解压缩后的字符串
否则输出字符串"!error"来报告错误
输入描述
输入一行,为一个ASCII字符串
长度不超过100字符
用例保证输出的字符串长度也不会超过100字符串
输出描述
若判断输入为合法的经过压缩后的字符串
则输出压缩前的字符串
若输入不合法 则输出字符串"!error"
示例一:
输入
4dff
输出
ddddff
说明
4d扩展为4个d ,故解压后的字符串为ddddff
示例二
输入
2dff
输出
!error
说明
2个d不需要压缩 故输入不合法
示例三
输入
4d@A
输出
!error
说明
全部由小写英文字母做成的字符串,压缩后不会出现特殊字符@和大写字母A
故输入不合法
// 字符串解压缩
// 解题思路:遍历每个字符,取出字符前的数字进行解压缩
public static void test062(){
Scanner sc = new Scanner(System.in);
String line = sc.nextLine();
// 替换掉合法字符
String replaceAll = line.replaceAll("[1-9]|[a-z]", "");
// 替换掉合法字符后,长度不为0,则不合法 || 最后一个字符是数字,不合法
if (replaceAll.length() > 0 || Character.isDigit(line.charAt(line.length() - 1))) {
System.out.println("!error");
return;
}
// 存放结果
String resLine = line;
for (int i = 0; i < line.length(); i++) {
char c = line.charAt(i);
// 获取字符前的数字
if (Character.isDigit(c)){
int start = i;
while (Character.isDigit(line.charAt(i+1))){
i++;
}
int num = Integer.parseInt(line.substring(start, i+1));
// 2不需要压缩,不合法
if (num <= 2) {
System.out.println("!error");
return;
}
// 解压缩
resLine = resLine.replaceFirst(num+"", getString(num, line.charAt(i + 1)));
}
}
System.out.println(resLine);
}
61. 相等的连续子串
给你两个字符串t和p
要求从t中找到一个和p相同的连续子串
并输出该子串第一个字符的下标
输入描述
输入文件包括两行 分别表示字符串t和p
保证t的长度不小于p
且t的长度不超过1000000
p的长度不超过10000
输出描述
如果能从t中找到一个和p相等的连续子串,
则输出该子串第一个字符在t中的下标
下标从左到右依次为1,2,3,...;
如果不能则输出 "No"
如果含有多个这样的子串
则输出第一个字符下标最小的
示例一:
输入:
AVERDXIVYERDIAN
RDXI
输出
4
// 相等的连续子串
// 解题思路:双层循环,遍历每个字符,依次判断是否与子串相同,当相同长度与子串相等时,结束并输出;否则进入下一个字符进行判断
public static void test061() {
Scanner sc = new Scanner(System.in);
String t = sc.nextLine();
String p = sc.nextLine();
for (int i = 0; i < t.length(); i++) {
// 开始字符位置
int start = i;
// 与子串相同字符个数
int j = 0;
// 与子串进行比对
while (start < t.length() && j < p.length() && t.charAt(start) == p.charAt(j)) {
// 索引位置向前
start++;
// 个数加1
j++;
}
// 当子串相同字符个数 == 子串长度,满足条件,输入并结束
if (j == p.length()) {
System.out.println(i + 1);
return;
}
}
System.out.println("No");
}
59.员工出勤奖
公司用一个字符串来标识员工的出勤信息
absent: 缺勤
late: 迟到
leaveearly:早退
present: 正常上班
现需根据员工出勤信息,判断本次是否能获得出勤奖,
能获得出勤奖的条件如下:
1.缺勤不超过1次
2.没有连续的迟到/早退
3.任意连续7次考勤 缺勤/迟到/早退 不超过3次
输入描述:
用户的考勤数据字符串记录条数 >=1
输入字符串长度 <10000 ;
不存在非法输入
如:
2
present
present absent present present leaveearly present absent
输出描述:
根据考勤数据字符串
如果能得到考勤奖输出true否则输出false
对于输出示例的结果应为
true false
示例一:
输入:
2
present
present present
输出:
true true
示例二
输入:
2
present
present absent present present leaveearly present absent
输出:
true false
// 员工出勤奖
// 解题思路:将输入的内容放在集合中,遍历集合,按条件依次判断
public static void test059() {
Scanner sc = new Scanner(System.in);
int num = Integer.parseInt(sc.nextLine());
List<String> list = new ArrayList<>();
for (int i = 0; i < num; i++) {
String line = sc.nextLine();
list.add(line);
}
for (int i = 0; i < list.size(); i++) {
String str = list.get(i);
String[] split = str.split(" ");
// 1.缺勤不超过1次
int absentCount = 0;
for (int j = 0; j < split.length; j++) {
if ("absent".equals(split[j])) {
absentCount++;
}
}
if (absentCount > 1) {
System.out.print(false + " ");
// 退出此次循环
continue;
}
// 2.没有连续的迟到/早退
if (str.contains("late leaveearly") || str.contains("leaveearly late") || str.contains("leaveearly leaveearly") || str.contains("late late")) {
System.out.print(false + " ");
// 退出此次循环
continue;
}
// 3.任意连续7次考勤 缺勤/迟到/早退 不超过3次
// 用于存放 缺勤/迟到/早退 最大次数
int count = 0;
// 用于存放 缺勤/迟到/早退 临时次数
int noPresent = 0;
if (split.length > 7) {
for (int j = 0; j + 7 <= split.length; j++) {
for (int k = j; k < 7 + j; k++) {
if ("absent".equals(split[k]) || "late".equals(split[k]) || "leaveearly".equals(split[k])) {
noPresent++;
}
}
count = Math.max(count, noPresent);
noPresent = 0;
}
} else {
for (int j = 0; j < split.length; j++) {
if ("absent".equals(split[j]) || "late".equals(split[j]) || "leaveearly".equals(split[j])) {
count++;
}
}
}
if (count > 3) {
System.out.print(false + " ");
// 退出此次循环
continue;
}
// 都符合,则输出true
System.out.print(true + " ");
}
}
更多华为od机试题请点这里<华为od机试题4 真题>,每篇8题,有更多的题也请告诉我啊