【题目】*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”.
【解题思路1】单栈
用栈,碰到数字、字母、左中括号都压入栈中,碰到右括号开始弹出,先弹出拿到字符串,再拿到数字(重复次数),把这一段转成字符串压入栈中,继续执行,最后把栈内存的reverse一下
class Solution {
int ptr;
public String decodeString(String s) {
LinkedList<String> stk = new LinkedList<String>();
ptr = 0;
while (ptr < s.length()) {
char cur = s.charAt(ptr);
if (Character.isDigit(cur)) {
// 遇到数字,进栈
String digits = getDigits(s);
stk.addLast(digits); //addLast()将指定元素追加在此列表的末尾
} 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());
}
//将出栈的字母反转
Collections.reverse(sub);
// 左括号出栈
stk.removeLast();
// 此时栈顶为当前 sub 对应的字符串应该出现的次数
int repTime = Integer.parseInt(stk.removeLast());
StringBuffer t = new StringBuffer();
String o = getString(sub);
// 构造重复n次的字符串
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();
}
public String getString(LinkedList<String> v) {
StringBuffer ret = new StringBuffer();
for (String s : v) {
ret.append(s);
}
return ret.toString();
}
}
class Solution {
public static String decodeString(String s) {
char[] chs = s.toCharArray();
//用 Object
Stack<Object> stack = new Stack<>();
// 计算中括号前的数字是多少,不一定是一位数。
int num = 0;
for (char c : chs) {
if (Character.isDigit(c)) {
// 1. 数字则直接计算
num = num * 10 + c - '0';
} else if (c == '[') {
// 2. 左括号, 先要把前面的数字放进去, 左中括号不用入栈
stack.push(num);
num = 0;
} else if (c == ']') {
// 3. 右括号, 出栈, 获取局部字符串再根据前面的数字得到乘次数再放入stack
String str = popAndGetString(stack);
int times = (int) stack.pop();
String temp = String.join("", Collections.nCopies(times, str));
stack.push(temp);
} else {
// 4. 正常字符, 放String类型
stack.push(String.valueOf(c));
}
}
return new StringBuilder(popAndGetString(stack)).reverse().toString();
}
// 这边一种情况是,前面可能已经变成正序的了,但是后面还有,后面来了,然后在这个方法中reverse一下就又变反了
// 那我干脆只在最终结果处reverse,其他过程不reverse
private static String popAndGetString(Stack<Object> stack) {
StringBuilder sb = new StringBuilder();
while (!stack.isEmpty() && stack.peek() instanceof String) {
sb.append(stack.pop());
}
return sb.toString();
}
}
【解题思路2】双栈
一个数字栈,一个字符串栈
出栈时遇到左括号,去数字栈取出一个数字
class Solution {
public String decodeString(String s) {
StringBuffer ans=new StringBuffer();
Stack<Integer> multiStack=new Stack<>();
Stack<StringBuffer> ansStack=new Stack<>();
int multi=0;
for(char c:s.toCharArray()){
if(Character.isDigit(c)){
multi=multi*10+c-'0';
}else if(c=='['){
ansStack.add(ans);
multiStack.add(multi);
ans=new StringBuffer();
multi=0;
}else if(Character.isAlphabetic(c)){
ans.append(c);
}else{
StringBuffer ansTmp=ansStack.pop();
int tmp=multiStack.pop();
for(int i=0;i<tmp;i++)ansTmp.append(ans);
ans=ansTmp;
}
}
return ans.toString();
}
}
转载:https://blog.csdn.net/XunCiy/article/details/106398467
查看评论