华为OD机试真题中,有一种关于字符串压缩表示的解压题目,其具体要求和相关解析如下:
一、题目描述
有一种简易压缩算法:针对全部由小写英文字母组成的字符串,将其中连续超过两个相同字母的部分压缩为连续个数加该字母,其他部分保持原样不变。例如,字符串“aaabbccccd”经过压缩成为字符串“3abb4cd”。
现在需要编写解压函数,根据输入的字符串,判断其是否为合法压缩过的字符串。若输入合法,则输出解压缩后的字符串;否则,输出字符串“!error”来报告错误。
二、输入描述
输入一行,为一个ASCII字符串,长度不超过100字符。用例保证输出的字符串长度也不会超过100字符。
三、输出描述
- 若判断输入为合法的经过压缩后的字符串,则输出压缩前的字符串。
- 若输入不合法,则输出字符串“!error”。
四、示例
输入
4dff
输出
ddddff
说明
:4d扩展为dddd,故解压后的字符串为“ddddff”。
输入
2dff
输出
!error
说明
:两个d不需要压缩,故输入不合法。
五、 解题思路
- 校验输入字符串是否合法:
合法与不合法的判定
-
合法:只有小写字母和数字组成,且数字必须大于2,数字后紧跟着字母。
-
不合法:
-
数字小于等于2;
-
数字后没有字母;
-
有两个以上连续的相同字符(这种已经是压缩过的形式);
-
出现非小写字母和非数字字符(例如特殊字符@和大写字母A等)。
-
首先检查字符串是否只包含小写字母和数字。
-
然后遍历字符串,检查数字是否大于2,数字后是否紧跟着字母,以及是否有连续的非法格式(如两个以上连续的相同字符,或数字后直接跟数字等)。
-
-
如果输入字符串合法,则进行解压操作:
- 遍历字符串,当遇到数字时,将后面的字母按照数字指定的次数重复拼接起来。
- 如果遇到字母,则直接添加到结果字符串中。
-
如果输入字符串不合法,则输出“!error”。
六、代码实现(Python示例)
def check(input_str):
# 检查字符串是否只包含小写字母和数字
if not input_str.isalnum():
return False
i = 0
while i < len(input_str):
c = input_str[i]
if c.isdigit():
num = int(c)
# 数字必须大于2
if num <= 2:
return False
# 数字后必须跟着字母
if i + 1 >= len(input_str) or not input_str[i + 1].isalpha():
return False
# 检查后续是否有非法格式(如连续相同字母的非法压缩)
next_char = input_str[i + 1]
j = i + 2
while j < len(input_str) and input_str[j] != next_char:
# 如果遇到相同字母前的数字,则是非法格式
if input_str[j].isdigit():
return False
j += 1
# 如果j没有跳出循环,说明有连续相同字母的非法压缩
if j < len(input_str) and input_str[j] == next_char:
return False
i += 2 # 跳过数字和紧跟的字母
else:
# 检查是否有三个或更多连续相同的字母
if i + 2 < len(input_str) and input_str[i] == input_str[i + 1] == input_str[i + 2]:
return False
i += 1
return True
def decompress(input_str):
builder = []
i = 0
while i < len(input_str):
c = input_str[i]
if c.isdigit():
num = int(c)
if i + 1 < len(input_str):
letter = input_str[i + 1]
builder.append(letter * num)
i += 2 # 跳过数字和紧跟的字母
else:
# 数字后没有字母,非法(但在check中已经处理,这里不会到达)
return "!error"
else:
builder.append(c)
i += 1
return ''.join(builder)
def main():
input_str = input().strip()
if not check(input_str):
print("!error")
else:
print(decompress(input_str))
if __name__ == "__main__":
main()
七、代码实现(java示例)
import java.util.Scanner;
public class StringDecompressor {
/**
* 检查输入的字符串是否为有效的压缩字符串
* 压缩字符串的定义规则如下:
* - 字符串中只能包含小写字母和数字
* - 数字必须大于2,并且必须紧接一个小写字母
* - 不能有连续相同的字母,除非它们被数字压缩
* - 不能有连续的数字
*
* @param input 待检查的字符串
* @return 如果字符串是有效的压缩字符串,则返回true;否则返回false
*/
public static boolean isValidCompressedString(String input) {
// 空字符串或null不是有效的压缩字符串
if (input == null || input.isEmpty()) {
return false;
}
// 遍历字符串中的每个字符
for (int i = 0; i < input.length(); i++) {
char currentChar = input.charAt(i);
// 如果当前字符是数字
if (Character.isDigit(currentChar)) {
int num = Character.getNumericValue(currentChar);
// 数字必须大于2
if (num <= 2) {
return false;
}
// 检查数字后是否紧跟着字母
if (i + 1 >= input.length() || !Character.isLowerCase(input.charAt(i + 1))) {
return false;
}
// 检查后续字符是否合法(避免连续相同字符的非法压缩形式)
char nextChar = input.charAt(i + 1);
if (i + 2 < input.length() && input.charAt(i + 2) == nextChar) {
// 如果数字后紧跟相同字母,检查是否再次被压缩(即是否有连续的数字)
if (Character.isDigit(input.charAt(i + 2))) {
return false;
}
// 否则,继续检查后续字符,确保没有连续相同字母(这已经是压缩形式)
for (int j = i + 2; j < input.length(); j++) {
if (input.charAt(j) == nextChar) {
return false;
}
}
}
// 跳过紧跟在数字后的字母,因为后续逻辑会处理它
i++;
} else if (!Character.isLowerCase(currentChar)) {
// 字符串中只能包含小写字母和数字
return false;
}
}
// 如果所有检查都通过,则字符串是有效的压缩字符串
return true;
}
/**
* 解压缩字符串中的数字和字母
* 对于输入字符串中的每个数字n,如果其后紧跟着一个字母,则将该字母重复n次添加到结果字符串中
* 如果字符不是数字,则直接添加到结果字符串中
*
* @param input 要解压缩的字符串,包含数字和小写字母
* @return 解压缩后的字符串
*/
public static String decompressString(String input) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < input.length(); i++) {
char currentChar = input.charAt(i);
// 检查当前字符是否为数字
if (Character.isDigit(currentChar)) {
int num = Character.getNumericValue(currentChar);
// 数字后必须紧跟着字母
if (i + 1 < input.length() && Character.isLowerCase(input.charAt(i + 1))) {
char letter = input.charAt(i + 1);
for (int j = 0; j < num; j++) {
result.append(letter);
}
i++; // 跳过紧跟在数字后的字母
}
} else {
// 直接添加字母到结果中
result.append(currentChar);
}
}
return result.toString();
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine().trim();
scanner.close();
if (isValidCompressedString(input)) {
System.out.println(decompressString(input));
} else {
System.out.println("!error");
}
}
}
八、运行实例解析
1. 调用 isValidCompressedString
方法
输入字符串 4dff
将被传递给 isValidCompressedString
方法进行验证。
- 首先,检查输入字符串是否为
null
或空字符串。4dff
不是null
也不是空字符串,因此继续。 - 遍历字符串中的每个字符:
i = 0
:当前字符是'4'
,是数字。- 数字
4
大于2
,符合条件。 - 检查
'4'
后是否紧跟着小写字母:下一个字符是'd'
,是小写字母,符合条件。 - 检查后续字符是否合法:跳过
'd'
,后续字符是'f'
和'f'
,但'f'
不是'd'
的重复,且'f'
后没有数字,因此这里不会返回false
。 - 跳过紧跟在数字后的字母
'd'
,将i
增加到1
。
- 数字
i = 1
:当前字符是'd'
,是小写字母,直接跳过。i = 2
:当前字符是'f'
,是小写字母,直接跳过。i = 3
:当前字符是'f'
,是小写字母,直接跳过。
- 所有检查都通过,字符串
4dff
是有效的压缩字符串。
2. 调用 decompressString
方法
输入字符串 4dff
将被传递给 decompressString
方法进行解压缩。
- 创建一个
StringBuilder
对象result
用于构建解压缩后的字符串。 - 遍历字符串中的每个字符:
i = 0
:当前字符是'4'
,是数字。- 数字
4
后紧跟着小写字母'd'
。 - 将
'd'
重复4
次添加到result
中:result
现在是"dddd"
。 - 跳过紧跟在数字后的字母
'd'
,将i
增加到1
。
- 数字
i = 1
:当前字符是'f'
,不是数字,直接添加到result
中:result
现在是"ddddf"
。i = 2
:当前字符是'f'
,不是数字,直接添加到result
中:result
现在是"ddddff"
。
- 遍历结束,返回
result.toString()
,即解压缩后的字符串"ddddff"
。
最终输出
程序输出解压缩后的字符串 ddddff
。
九、注意事项
- 在校验字符串时,要仔细检查各种不合法的情况,确保输入字符串符合压缩算法的要求。
- 在解压过程中,要注意正确处理数字和其后面的字母,避免索引越界或重复添加字符等问题。
以上即为华为OD机试中关于字符串压缩表示的解压题目的详细介绍、解题思路以及代码实现示例。