华为OD机试 2024D卷题库疯狂收录中,刷题点这里
专栏导读
本专栏收录于《华为OD机试(JAVA)真题(D卷+C卷+A卷+B卷)》。
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。
一、题目描述
题目描述
有一种校验证码机制,用于数据传输中的数据完整性检查,规则如下:
- 在字符串中插入一些数字作为校验证码,每个数字之后跟随对应个数的字符;
- 要求有校验证码(校验证码大于零并且无前导零),并且正确匹配,无歧义:如,“helloworld” 在插入校验证码之后可以为 “5hello5world”,即 5 + “hello” + 5 + “world”;
但是,有些字符串在进行校验时会产生歧义,比如 “109something” 可以校验为 10 + “9something” 或者 1 + “0” + 9 + “something”,故这类编码方式是有歧义的。
现给出一个字符串 encodedString,请判断这个字符串是否符合上述规则:
- 如果是,则返回去掉校验码后的字符串长度;
- 如果不是,则返回 -1。
二、测试用例
测试用例1:
1、输入
9computer012
2、输出
10
3、说明
只可以解析为 9 + “computer0” + 1 + “2”,可以正确匹配(校验证码与随后字符个数相同)且无歧义。返回去掉校验码后的字符串 “computer02” 的长度 10。
测试用例2:
1、输入
118computer1a
2、输出
-1
3、说明
可以解析为 11 + “8computer1a” 或 1 + “1” + 8 + “computer” + 1 + “a”,有两种解析方式,所以有歧义。
五、解题思路
题目的核心是对包含校验码的字符串进行验证,并去除校验码,返回去除校验码后的字符串长度。如果字符串不符合校验规则或存在歧义,则返回 -1。
1、解题步骤
- 检查输入字符串:
- 如果输入字符串为空,返回0,因为没有校验码。
- 如果字符串的第一个字符不是有效的校验码(1-9),返回 -1。
- 初始化数据结构:
- 使用 List 保存可能的解析结果。
- 使用 StringBuilder 累积当前的校验码字符。
- 遍历字符串:
- 逐字符遍历输入字符串。
- 如果当前字符是数字字符,将其添加到 checksum 中,形成当前的校验码。
- 将累积的 checksum 转换为整数,表示后续字符串段的长度。
- 检查当前解析位置后剩余字符串是否足够长,不足则跳过当前解析。
- 对剩余字符串进行递归解析,获取剩余部分的长度。
- 如果递归解析成功,将当前段长度和剩余段长度相加,并添加到 results 列表中。
- 如果当前字符不是数字字符,结束循环,因为校验码已经结束,接下来应该是字符串段。
- 结果判断:
- 检查 results 列表的大小,如果列表中只有一个结果,则返回该结果,表示解析成功且无歧义。
- 如果列表中有多个结果或为空,返回 -1,表示解析失败或存在歧义。
2、关键点
(1)递归解析:对每一段进行递归解析,以验证剩余部分是否符合校验规则。
(2)歧义检测:通过检查 results 列表的大小来确定是否存在歧义。
(3)长度校验:在每一步都检查剩余字符串的长度,以确保不会超出范围。
六、Java算法源码
public class OdTest02 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in); // 创建Scanner对象以读取用户输入
String inputString = scanner.nextLine(); // 从控制台读取输入字符串
int length = validateChecksum(inputString); // 调用validateChecksum方法进行校验
System.out.println(length); // 输出校验结果
}
public static int validateChecksum(String inputString) {
if (inputString.isEmpty()) { // 如果输入字符串为空,返回0
return 0;
}
// 检查输入字符串的第一个字符是否是有效的校验码(1-9)
if (inputString.charAt(0) < '1' || inputString.charAt(0) > '9') {
return -1; // 如果不是有效的校验码,返回-1
}
List<Integer> results = new ArrayList<>(); // 用于存储各个解析结果的列表
StringBuilder checksum = new StringBuilder(); // 用于累积当前的校验码
for (int i = 0; i < inputString.length(); i++) { // 遍历输入字符串中的每一个字符
char currentChar = inputString.charAt(i); // 获取当前字符
if (currentChar >= '0' && currentChar <= '9') { // 如果当前字符是数字
checksum.append(currentChar); // 将当前字符追加到校验码中
int segmentLength = Integer.parseInt(checksum.toString()); // 将校验码转换为整数,表示后面段的长度
if (i + segmentLength + 1 > inputString.length()) continue; // 如果超出字符串长度,继续下一个字符
// 递归调用validateChecksum方法以解析剩余部分
int remainingLength = validateChecksum(inputString.substring(i + segmentLength + 1));
if (remainingLength == -1) continue; // 如果解析失败,继续下一个字符
// 解析成功,将当前段长度和剩余段长度相加,并添加到结果列表中
results.add(segmentLength + remainingLength);
} else {
break; // 如果遇到非数字字符,结束循环
}
}
// 如果结果列表中只有一个元素,返回该元素值,否则返回-1表示失败
return results.size() == 1 ? results.get(0) : -1;
}
}
七、效果展示
1、输入
9computer012
2、输出
10
3、说明
只可以解析为 9 + “computer0” + 1 + “2”,可以正确匹配(校验证码与随后字符个数相同)且无歧义。返回去掉校验码后的字符串 “computer02” 的长度 10。
🏆下一篇:华为OD机试 - 简易内存池 - 逻辑分析(Java 2024 D卷 200分)
🏆本文收录于,华为OD机试(JAVA)真题(D卷+C卷+A卷+B卷)
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。