全网最全面的华为OD机试真题汇总,100%原题题库,不需要开会员即可查看全部内容,更多考题请查看真题库。
真题库:https://www.yuque.com/codernav.com/od
题目:简单的解压缩算法
知识点栈
时间限制:1s 空间限制:256MB 限定语言:不限
题目描述:
现需要实现一种算法,能将一组压缩字符串还原成原始字符串,还原规则如下:
1、字符后面加数字N,表示重复字符N次。例如:压缩内容为A3,表示原始字符串为AAA。
2、花括号中的字符串加数字N,表示花括号中的字符串重复N次。例如:压缩内容为{AB}3,表示原始字符串为ABABAB。
3、字符加N和花括号后面加N,支持任意的嵌套,包括互相嵌套。例如:压缩内容可以{A3B1{C}3}3。
输入描述:
输入一行压缩后的字符串
输出描述:
输出压缩前的字符串
补充说明:
输入保证,数字不会为0,花括号中的内容不会为空,保证输入的都是合法有效的压缩字符串
输入输出字符串区分大小写
输入的字符串长度为范围[1, 10000]
输出的字符串长度为范围[1, 100000]
数字N范围[1, 10000]
示例1
输入:
A3
输出:
AAA
说明:
A3代表A字符重复3次
示例2
输入:
{A3B1{C}3}3
输出:
AAABCCCAAABCCCAAABCCC
说明:
{A3B1{C}3}3代表A字符重复3次,B字符重复1次,花括号中的C字符重复3次,最外层花括号中的AAABCCC重复3次
解题思路:
例如:{A3B1{C}3{x2Y}2L4}3
使用双向队列deque来放置字符串,使用tempStr来放置临时字符串,isHasBrace代表是有大括号需要处理,初始化false
1、从头开始遍历,遍历到“{”,isHasBrace=false且tempStr为空,则deque=【{】;
继续遍历,直到第二个“{”,isHasBrace=false但是tempStr有值,则进行处理后放入队列中,deque=【{,AAAB,{】;
2、遍历到“}”,tempStr=“C”,因为isHasBrace=false,所以先处理完tempStr放入队列中,deque=【{,AAAB,{,C】,isHasBrace置为true;
3、遍历到“{”,因为isHasBrace=true,需要处理大括号:遍历队列,发现括号里面只有一个C,此时tempStr=3,处理完放入队列中:deque=【{,AAAB,CCC,{】,isHasBrace置为false;
4、遍历到“}”,tempStr=“x2Y”,因为isHasBrace=false,所以先处理完tempStr放入队列中,deque=【{,AAAB,CCC,{,xxY】,isHasBrace置为true;
5、遍历到“L”,因为L是字符且isHasBrace=true,需要处理大括号:遍历队列,发现括号里面是xxY,此时tempStr=2,处理完放入队列中:deque=【{,AAAB,CCC,xxYxxY】,isHasBrace置为false;
6、遍历到“}”,tempStr=“L4”,因为isHasBrace=false,所以先处理完tempStr放入队列中,deque=【{,AAAB,CCC,xxYxxY,LLLL】,isHasBrace置为true;
7、遍历到最后tempStr=3,isHasBrace=true,需要处理大括号:遍历队列,发现括号里面是AAABCCCxxYxxYLLLL,此时tempStr=3,处理完放入队列中:deque=【AAABCCCxxYxxYLLLLAAABCCCxxYxxYLLLLAAABCCCxxYxxYLLLL】。
最终从头输出队列为:AAABCCCxxYxxYLLLLAAABCCCxxYxxYLLLLAAABCCCxxYxxYLLLL
代码实现一:
package com.codernav.demo.hwod.exam;
import java.util.*;
/**
* @title 简单的解压缩算法
* @Description 现需要实现一种算法,能将一组压缩字符串还原成原始字符串,还原规则如下:
* 1、字符后面加数字N,表示重复字符N次。例如:压缩内容为A3,表示原始字符串为AAA。
* 2、花括号中的字符串加数字N,表示花括号中的字符串重复N次。例如:压缩内容为{AB}3,表示原始字符串为ABABAB。
* 3、字符加N和花括号后面加N,支持任意的嵌套,包括互相嵌套。例如:压缩内容可以{A3B1{C}3}3。
* @Author 开发者导航
* @website https://codernav.com
* @date 2023/5/28
*/
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String string = sc.nextLine();
int len = string.length();
Deque<String> strDeque = new ArrayDeque<>();
String tempStr = ""; //字符串
boolean isHasBraces = false; //是否有大括号需要处理
for (int i = 0; i < len; i++) {
char c = string.charAt(i);
if (c == '{') { //遇到左括号
if (isHasBraces) { //先判断是否有大括号需要处理
handleBraces(tempStr, strDeque);
isHasBraces = false;
} else if (!tempStr.isEmpty()) {
strDeque.addLast(handle(tempStr));
}
strDeque.addLast(String.valueOf(c));
tempStr = "";
} else if (c == '}') {
strDeque.addLast(tempStr);
if (isHasBraces) {
handleBraces(strDeque.pollLast(), strDeque);
} else {
strDeque.addLast(handle(Objects.requireNonNull(strDeque.pollLast())));
}
isHasBraces = true;
tempStr = "";
} else {
if (isHasBraces && Character.isLetter(c)) {
handleBraces(tempStr, strDeque);
isHasBraces = false;
tempStr = "";
}
tempStr += c;
}
if (i == len - 1) { //最后一个字符
if (isHasBraces) {
handleBraces(tempStr, strDeque);
} else {
strDeque.addLast(handle(tempStr));
}
}
}
StringBuilder res = new StringBuilder();
while (strDeque.size() != 0) {
res.append(strDeque.pollFirst());
}
System.out.println(res);
}
/**
* 获取大括号里面的字符串
*
* @param strDeque
* @return
*/
public static String getBraces(Deque<String> strDeque) {
List<String> list = new ArrayList<>();
while (!strDeque.peekLast().equals("{")) { //直至碰到下一个左括号
list.add(strDeque.pollLast());
}
strDeque.pollLast(); //左括号也需要删除
Collections.reverse(list); //因为是从尾部开始找的所以需要翻转
String res = "";
for (String s : list) {
res += s;
}
return res;
}
/**
* 处理大括号里面的内容
*
* @param tempStr 括号外的数字
* @param strDeque 字符串队列
*/
public static void handleBraces(String tempStr, Deque<String> strDeque) {
int num = Integer.parseInt(tempStr);
StringBuilder temp = new StringBuilder();
String strInBraces = getBraces(strDeque);
for (int j = 0; j < num; j++) {
temp.append(strInBraces);
}
strDeque.addLast(temp.toString());
}
/**
* 处理连续的字符串
*
* @param str
* @return
*/
public static String handle(String str) {
int len = str.length();
String res = "";
String tempStr = ""; //字符串
StringBuilder tempNum = new StringBuilder(); //数字字符串(处理多位数)
for (int i = 0; i < len; i++) {
char c = str.charAt(i);
if (Character.isDigit(c)) { //此时是数字
tempNum.append(c); //是数字直接进行拼接
} else { //此时是字母
if (tempNum.length() > 0) { //数字字符串不为空说明需要处理
int num = Integer.parseInt(tempNum.toString()); //字符重复的次数
for (int j = 0; j < num; j++) {
res += tempStr; //重复多少次就拼接多少次
}
tempStr = ""; //处理完需要置空以免影响下一个字符的统计
tempNum = new StringBuilder(); //数字一样置空
}
tempStr += c; //字符拼接
}
if (i == len - 1) { //不能忘了处理最后一位
if (tempNum.length() > 0) { //数字字符串不为空时处理
int num = Integer.parseInt(tempNum.toString());
for (int j = 0; j < num; j++) {
res += tempStr;
}
} else {
res += tempStr; //为空时直接拼接字符串(处理单字符串的情况)
}
}
}
return res;
}
}
代码实现二:Java代码满分实现
package com.codernav.demo.hwod.exam;
import java.util.Scanner;
import java.util.Stack;
/**
* @title 简单的解压缩算法
* @Description 现需要实现一种算法,能将一组压缩字符串还原成原始字符串,还原规则如下:
* 1、字符后面加数字N,表示重复字符N次。例如:压缩内容为A3,表示原始字符串为AAA。
* 2、花括号中的字符串加数字N,表示花括号中的字符串重复N次。例如:压缩内容为{AB}3,表示原始字符串为ABABAB。
* 3、字符加N和花括号后面加N,支持任意的嵌套,包括互相嵌套。例如:压缩内容可以{A3B1{C}3}3。
* @Author 开发者导航
* @website https://codernav.com
* @date 2023/5/28
*/
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String str = in.nextLine();
System.out.println(solution(str));
}
public static String repeat(String str, int num) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < num; i++) {
sb.append(str);
}
return sb.toString();
}
public static String solution(String str) {
Stack<String> stack = new Stack<>();
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (c == '{') {
stack.push("{");
} else if (c == '}') {
if (Character.isDigit(str.charAt(i + 1))) {
int p = i + 1;
while (p < str.length() && Character.isDigit(str.charAt(p))) p++;
int num = Integer.parseInt(str.substring(i + 1, p));
StringBuilder sb = new StringBuilder();
while (!stack.peek().equals("{")) {
String s = stack.pop();
sb.append(s);
}
stack.pop();
stack.push(repeat(sb.toString(), num));
i = p - 1;
}
} else if (Character.isAlphabetic(c)) {
if (Character.isDigit(str.charAt(i + 1))) {
int p = i + 1;
while (p < str.length() && Character.isDigit(str.charAt(p))) p++;
int num = Integer.parseInt(str.substring(i + 1, p));
stack.push(repeat(c + "", num));
i = p - 1;
} else {
stack.push(c + "");
}
}
}
StringBuilder sb = new StringBuilder();
while (!stack.isEmpty()) {
sb.append(stack.pop());
}
String str0 = sb.toString();
sb = new StringBuilder();
for (int i = str0.length() - 1; i >= 0; i--) {
sb.append(str0.charAt(i));
}
return sb.toString();
}
}
