LeetCode——394.字符串解码
题目
394.字符串解码
给定一个经过编码的字符串,返回它解码后的字符串。
编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。
你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。
此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。
示例:
s = “3[a]2[bc]”, 返回 “aaabcbc”.
s = “3[a2[c]]”, 返回 “accaccacc”.
s = “2[abc]3[cd]ef”, 返回 “abcabccdcdcdef”.
解析
利用栈的思想,跟编译原理差不多,注意这种坑 3[a2[c]]
,第一次是按照第一个例子3[a]2[bc]
写的,写完才发现还有嵌套的情况,还要注意的是前面的数字可能是多位数,下面直接用的官方题解,我加了详细的注释,比较好理解。大致思路就是判断当前字符①是数字,②是字母或者左括号 [,③是右括号,不同的情况进行对应的处理。这里用LinkedList来模仿栈,且泛型是String,处理多位数时,直接出一次栈就行,数字入栈前经过了处理,存入的是多位数的String。
代码
class Solution {
int ptr; //定义一个下标指针
public String decodeString(String s) {
LinkedList<String> stk = new LinkedList<String>(); //LinkedList模仿stack,方便遍历
ptr = 0; //下标指针,初始化为0
while (ptr < s.length()) {
char cur = s.charAt(ptr); //获取下标指针对应的当前字符
if (Character.isDigit(cur)) { //isDigit() 方法用于判断指定字符是否为数字。
// 获取一个数(可能是多位数)并进栈
String digits = getDigits(s); //把所有的数字(可能是多位数)存到digits字符串中
stk.addLast(digits); //入栈
} else if (Character.isLetter(cur) || cur == '[') {
// 左括号或者字母则进栈
stk.addLast(String.valueOf(s.charAt(ptr++)));
} else { //这一步说明是右括号],对当前栈内的元素进行处理
++ptr;
LinkedList<String> sub = new LinkedList<String>();
while (!"[".equals(stk.peekLast())) { //当不是左括号时
sub.addLast(stk.removeLast()); //出栈存放到sub中
}
Collections.reverse(sub); //sub反转,因为出栈的顺序是反的
// 左括号出栈
stk.removeLast();
// 此时栈顶为当前 sub 对应的字符串应该出现的次数
//注意由于前面对多位数进行了处理,这里出栈是String类型,所以转为整形就直接是多位数了。不是单个字符出栈
int repTime = Integer.parseInt(stk.removeLast()); //获取次数
StringBuffer t = new StringBuffer(); //用来存放构造的字符串
String o = getString(sub); //获取sub中的字符串
// 构造字符串
while (repTime-- > 0) {
t.append(o);
}
// 将构造好的字符串入栈
stk.addLast(t.toString());
}
}
return getString(stk);
}
//获取字符串中的当前位置的数字,拼接成一个新的字符串
public String getDigits(String s) {
StringBuffer ret = new StringBuffer();
while (Character.isDigit(s.charAt(ptr))) { //循环是因为可能是多位数
ret.append(s.charAt(ptr++));
}
return ret.toString();
}
//获取LinkedList中的字符串
public String getString(LinkedList<String> v) {
StringBuffer ret = new StringBuffer();
for (String s : v) {
ret.append(s);
}
return ret.toString();
}
}