【华为OD-E卷 - 一种字符串压缩表示的解压 100分(python、java、c++、js、c)】
题目
有一种简易压缩算法:针对全部由小写英文字母组成的字符串,将其中连续超过两个相同字母的部分压缩为连续个数加该字母,其他部分保持原样不变。
例如:字符串“aaabbccccd”经过压缩成为字符串“3abb4cd”。
请您编写解压函数,根据输入的字符串,判断其是否为合法压缩过的字符串,
若输入合法则输出解压缩后的字符串,否则输出字符串“!error”来报告错误
输入描述
- 输入一行,为一个ASCII字符串,长度不会超过100字符,用例保证输出的字符串长度也不会超过100字符
输出描述
- 若判断输入为合法的经过压缩后的字符串,则输出压缩前的字符串;
若输入不合法,则输出字符串“**!error**”
用例
用例一:
输入:
4dff
输出:
ddddff
用例二:
输入:
2dff
输出:
!error
用例三:
输入:
4d@A
输出:
!error
python解法
- 解题思路:
- 这段代码的目标是实现对一个压缩字符串的解压操作。输入的压缩字符串满足以下条件:
字符串是由字母和数字组成,数字表示前面字母的重复次数。
解压后的字符串需要符合原压缩规则。
具体步骤如下:
输入字符串的合法性检查:首先判断字符串中是否含有非小写字母和数字的字符,如果有则直接返回 !error。
解压过程:遍历压缩字符串,如果遇到数字,则认为它表示后一个字符的重复次数,根据数字展开字符;如果数字无效(如小于等于2,或后面没有字母),返回 !error。
压缩验证:解压后的字符串如果经过压缩后不再得到原始的压缩字符串,说明解压有问题,返回 !error。
返回解压后的字符串:如果解压顺利且验证通过,返回解压后的字符串
import re
def decompress_string(input_string):
# 使用正则表达式检查字符串中是否包含非小写字母和数字的字符
if re.search(r"[^a-z0-9]", input_string):
return "!error" # 如果包含其他字符,返回错误
result = [] # 用来存储解压后的结果
i = 0 # 遍历输入字符串的指针
while i < len(input_string):
if input_string[i].isdigit(): # 如果当前字符是数字
count = int(input_string[i]) # 获取数字值,表示下一个字母的重复次数
if count <= 2 or i + 1 >= len(input_string) or not input_string[i + 1].isalpha():
# 如果数字小于等于2,或者数字后面不是字母,或者没有字母,说明格式错误
return "!error"
result.append(input_string[i + 1] * count) # 重复字母并添加到结果列表
i += 2 # 跳过数字和字母
else:
result.append(input_string[i]) # 如果当前是字母,直接添加到结果列表
i += 1 # 移动到下一个字符
# 解压后的字符串进行再次压缩,如果压缩后的结果不等于原始输入,说明解压有误
if compress("".join(result)) != input_string:
return "!error"
return "".join(result) # 返回解压后的字符串
def compress(text):
compressed = [] # 用来存储压缩后的结果
i = 0 # 遍历字符串的指针
while i < len(text):
count = 1 # 初始化重复次数为1
while i + 1 < len(text) and text[i] == text[i + 1]: # 找到连续相同的字符
count += 1 # 计数器加1
i += 1 # 指针移动到下一个字符
if count > 2: # 如果字符重复次数大于2,进行压缩
compressed.append(f"{count}{text[i]}") # 添加压缩后的格式 "数量+字符"
else: # 否则将字符按原样添加
compressed.extend([text[i]] * count)
i += 1 # 移动到下一个不同的字符
return "".join(compressed) # 返回压缩后的字符串
# 测试部分
s = input()
print(decompress_string(s)) # 输出解压后的字符串或错误信息
java解法
- 解题思路
- 该程序的目标是处理一个压缩格式的字符串,并对其进行解压缩操作,解压的结果要符合特定的规则,若不符合要求,则返回 !error。
合法性检查: 首先检查字符串是否只包含小写字母和数字。如果包含其他字符,则返回 !error。
正则表达式匹配: 使用正则表达式 (\d+)([a-z]) 来查找所有数字和字母的组合。数字代表后面字母的重复次数,如果数字小于等于2或者格式不对,返回 !error。
解压缩: 将匹配到的数字和字母按照规则展开,将字母按数字指定的次数重复。
压缩验证: 解压后的字符串要经过压缩操作,如果压缩后的结果不等于原始的输入字符串,则说明解压过程有误,返回 !error。
返回解压后的字符串: 如果解压和验证都通过,则返回解压后的字符串
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine(); // 读取输入的字符串
System.out.println(getResult(input)); // 输出解压结果或错误信息
}
// 主要的解压函数
public static String getResult(String str) {
String originalStr = str; // 保存原始的输入字符串,用于后续验证
// 如果输入字符串包含非小写字母或数字的字符,则返回错误
if (!str.matches("[a-z0-9]*")) {
return "!error";
}
// 正则表达式匹配,寻找数字和字母的组合
Pattern regExp = Pattern.compile("(\\d+)([a-z])");
Matcher matcher = regExp.matcher(str);
// 逐个匹配数字和字母的组合
while (matcher.find()) {
String match = matcher.group(); // 获取匹配的字符串
int repeatTimes = Integer.parseInt(matcher.group(1)); // 获取数字部分,即字母重复的次数
char character = matcher.group(2).charAt(0); // 获取字母部分
// 如果数字小于等于2,则返回错误
if (repeatTimes <= 2) {
return "!error";
}
// 扩展字母,重复指定的次数
String expanded = String.valueOf(character).repeat(repeatTimes);
// 替换原字符串中的数字和字母组合为扩展后的字符串
str = str.replace(match, expanded);
}
// 进行压缩验证,检查解压后的字符串是否能还原为原始输入字符串
if (!zip(str).equals(originalStr)) {
return "!error";
}
return str; // 返回解压后的字符串
}
// 压缩函数:将解压后的字符串进行压缩
public static String zip(String str) {
StringBuilder compressed = new StringBuilder(); // 用于构建压缩后的字符串
int i = 0; // 遍历字符串的指针
// 遍历字符串,压缩相同的字符
while (i < str.length()) {
int count = 1; // 初始化字符的重复次数为1
// 找到连续重复的字符
while (i + 1 < str.length() && str.charAt(i) == str.charAt(i + 1)) {
count++; // 计数器加1
i++; // 移动指针
}
// 如果字符的重复次数大于2,则压缩为 "数量+字符" 的形式
if (count > 2) {
compressed.append(count).append(str.charAt(i));
} else {
// 否则将字符按原样添加
compressed.append(String.valueOf(str.charAt(i)).repeat(count));
}
i++; // 移动到下一个不同的字符
}
return compressed.toString(); // 返回压缩后的字符串
}
}
C++解法
- 解题思路
更新中
C解法
更新中
JS解法
具体步骤如下:
合法性检查:
输入字符串必须只包含小写字母(a-z)和数字(0-9)。如果包含其他字符,立即返回 !error。
正则表达式匹配:
使用正则表达式 (\d+)([a-z]) 来查找所有数字和字母的组合。数字表示字母的重复次数,字母是要被重复的字符。
每次匹配到的数字需要满足重复次数大于2。如果数字小于等于2,则返回 !error。
对每个匹配项,将数字指定的字符重复相应的次数,并替换原字符串中的匹配部分。
解压完成后的压缩验证:
对解压后的字符串执行压缩操作(即通过 zip 函数)。如果压缩后的字符串和原始输入字符串不一致,说明解压过程出现了错误,返回 !error。
返回解压后的字符串:
如果解压和验证都成功,则返回解压后的字符串
const readline = require("readline");
// 创建接口以读取标准输入
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
// 监听每一行输入,处理并输出结果
rl.on("line", (line) => {
console.log(getResult(line)); // 输出处理结果
});
// 主函数:处理解压逻辑
function getResult(str) {
const originalStr = str; // 保存原始输入,用于后续验证
// 如果输入字符串包含非小写字母或数字的字符,直接返回错误
if (/[^a-z0-9]/.test(str)) {
return "!error";
}
// 正则表达式匹配:查找数字+字母的组合
const regExp = /(\d+)([a-z])/g;
// 持续处理所有匹配的数字和字母组合
while (true) {
const match = regExp.exec(str); // 查找下一个匹配项
if (!match) break; // 如果没有更多匹配项,则退出循环
// 解构匹配结果:src为匹配的整个字符串,repeatTimesStr为数字部分,char为字母部分
const [src, repeatTimesStr, char] = match;
const repeatTimes = parseInt(repeatTimesStr, 10); // 将数字部分转为整数
// 如果数字小于等于2,表示格式不合法,返回错误
if (repeatTimes <= 2) {
return "!error";
}
// 扩展字母部分,按照重复次数进行重复
const expanded = char.repeat(repeatTimes);
// 替换原字符串中的数字和字母组合为展开后的字母部分
str = str.replace(src, expanded);
}
// 完成解压后,对解压结果进行压缩验证
if (zip(str) !== originalStr) {
return "!error"; // 如果压缩结果不匹配原始输入,说明解压错误
}
return str; // 返回解压后的字符串
}
// 压缩函数:将解压后的字符串进行压缩
function zip(str) {
let compressed = []; // 用来存储压缩后的字符
let i = 0; // 字符串遍历指针
// 遍历字符串并压缩连续相同的字符
while (i < str.length) {
let count = 1; // 初始化连续字符的计数为1
// 查找连续相同的字符
while (i + 1 < str.length && str[i] === str[i + 1]) {
count++; // 计数器加1
i++; // 移动指针
}
// 如果字符的重复次数大于2,则压缩成 "数量+字符" 的形式
if (count > 2) {
compressed.push(`${count}${str[i]}`);
} else {
// 否则直接将字符按原样添加
compressed.push(str[i].repeat(count));
}
i++; // 移动到下一个不同的字符
}
// 返回压缩后的字符串
return compressed.join("");
}
注意:
如果发现代码有用例覆盖不到的情况,欢迎反馈!会在第一时间修正,更新。
解题不易,如对您有帮助,欢迎点赞/收藏