题目链接:https://leetcode.cn/problems/decode-string/
思路:该题目实际是一个括号匹配的问题,括号匹配问题用的数据结构就是栈。核心逻辑是构造两个栈(数字栈+字母栈),从左到右遍历字符串,遇到数字压入数字栈,遇到括号数字栈弹出,并将括号压入字母栈,遇到另一个匹配的括号时弹出所有字母和括号,并结合数字决定重复次数输出。
但是实际在写代码时候也遇到很多问题,有些细节条件还是没有考虑的太周到,最后还是在本异一点一点debug出来了,花了多半天的时间。代码如下:
class Solution {
public static String decodeString(String s) {
Stack<String> numStack = new Stack<String>();
//用于将类似1,0的字符串拼接为10
Stack<String> tranNumStack = new Stack<String>();
Stack<String> opStack = new Stack<String>();
StringBuilder result = new StringBuilder();
int index = 0;
while (index < s.length()) {
if (Character.isLetter(s.charAt(index)) || "[".equals(s.substring(index, index+1))) {
if(!tranNumStack.isEmpty()) {
//先弹出之前的数字栈中的字符并转换为数字重新压入
StringBuilder builder = new StringBuilder();
while (!tranNumStack.isEmpty()) {
builder.append(tranNumStack.pop());
}
//倒序并存入numStack栈
numStack.push(builder.reverse().toString());
}
//字母和左括号压入字符栈
while (index < s.length() && (Character.isLetter(s.charAt(index)) || "[".equals(s.substring(index, index+1)))) {
opStack.push(s.substring(index, index+1));
index++;
}
}else if(Character.isDigit(s.charAt(index))) {
//数字直接压栈
while (index < s.length() && Character.isDigit(s.charAt(index))) {
tranNumStack.push((s.substring(index, index+1)));
index++;
}
}else if("]".equals(s.substring(index, index+1))) {
StringBuilder sb = new StringBuilder();
//右括号开始出栈
while(!"[".equals(opStack.peek())) {
sb.insert(0, opStack.pop());
}
//弹出左括号
opStack.pop();
//与数字结合生成解码后的字符串并压栈
if(!numStack.isEmpty()) {
String join = String.join("", Collections.nCopies(Integer.parseInt(numStack.pop()), sb.toString()));
opStack.push(join);
}
index++;
}
}
//将所有的字符逆序输出
while (!opStack.isEmpty()) {
result.insert(0, opStack.pop());
}
return result.toString();
}
}
比较关键的逻辑总结起来有以下几点:
1.除了数字栈numStack和字符栈opStack之外,加入了另一个临时数字栈tranNumStack,目的是将多位数(如:10)合并为一个真实的数字再压入numStack中。
2.遇到数字直接入栈
3.遇到字符(非右括号),先把前面暂存的倍数(存在tranNumStack中)转换为真实的数字,并存入numStack中(注意倒序)。接着依次将字符存入opStack之中。
4.遇到右括号,就需要处理之前与之匹配的左括号及倍数,转换为需要的形式,并存入opStack。
5.将opStack中的所有元素倒序依次输出。
总体感受,这种中等难度的题目想要一时半会解出来还是比较难的(至少对于我来讲),可以结合一些题解来思考,但是最关键的还是要自己静下来一步一步思考,甚至在本地一步一步debug。如果自己没有很深的思考,别人的代码也很难看懂,就算看懂了后面还是会容易忘记。