class Solution {
public String decodeString(String s) {
int k = 0;
StringBuilder res = new StringBuilder();
Stack<Integer> kstack = new Stack<>();
Stack<StringBuilder> restack = new Stack<>();
for(char c : s.toCharArray()){
if(c == '['){
//碰到括号,记录K和当前res,归零。
kstack.push(k);
restack.push(res);
k = 0;
res = new StringBuilder();
}else if(c ==']'){
//出最近的一个左括号入的k,当前res进行计算不入栈
int curk = kstack.pop();
StringBuilder temp = new StringBuilder();
for(int i = 0; i < curk; i++){
temp.append(res);
}
//与括号外合并
res = restack.pop().append(temp);
}else if(c >= '0' && c <= '9'){
k = c - '0' + k * 10;
//如果k是多位数需要x10
}else{
res.append(c);
//如果是字母则缓慢添加
}
}
return res.toString();
}
}
public String decodeString(String s) {
// 思路: 乘法和 递推公式 前一个和作为下一个加法的加数
// 3[a]2[bc] = 3a+2bc = (3a + "") + 2bc
// 3[a2[c]] = 3(2c + a) = 3(2c + a) + ""
// 1. 初始化倍数和res 及其对应栈
int multi = 0;
StringBuilder res = new StringBuilder();
Deque<Integer> multi_stack = new LinkedList<>();
Deque<String> res_stack = new LinkedList<>();
// 2. 遍历字符
char[] chars = s.toCharArray();
for (char ch : chars) {
// 3. 统计倍数
if (ch >= '0' && ch <= '9')
multi = multi * 10 + (ch - '0');
// 4. 统计res
else if (ch >= 'a' && ch <= 'z')
res.append(ch);
// 5. 入栈并重置临时变量
else if (ch == '[') {
multi_stack.push(multi);
res_stack.push(res.toString());
// 重置开始下一轮重新统计
multi = 0;
res = new StringBuilder();
// 6. 出栈做字符串乘法和加法
} else {
int cur_multi = multi_stack.pop();
StringBuilder temp = new StringBuilder();
// 乘以当前统计字符串res
for (int i = 0; i < cur_multi; i++)
temp.append(res);
// 加上前一个统计字符串作为当前res
res = new StringBuilder(res_stack.pop() + temp);
}
}
return res.toString();
}
C++
string decodeString(string s) {
//两个栈分别压int res和用pair
stack<pair<int, string>> sta;
int num = 0; string res = "";
//循环检查字符串
for (int i = 0; i < s.size(); i++) {
//遇到数字则存入num
if (s[i] >= '0'&&s[i] <= '9') {
num *= 10;//num=num*10
num += (s[i] - '0');//这里括号是否需要
}
else if (s[i] == '[') {//遇到[压栈数字和字符串,置零置空
sta.push(make_pair(num, res));
num = 0;
res = "";
}
else if (s[i] == ']') {//遇到]出栈数字和字符串,组装
int n = sta.top().first;//n指示的是res的循环次数,不是a的
string a = sta.top().second;
sta.pop();
for (int i = 0; i < n; i++) a = a + res; //循环n次
res = a;
}
else {//遇到字符存入字符
res += s[i];
}
}
return res;
}
class Solution {
public String decodeString(String s) {
return dfs(s, 0)[0];
}
//首先解释下String[]是什么
//当String[]的长度为2时,第二个元素为解码出的子字符串,
第一个元素为解码出的子字符串的最后字符']'在s中的下标
//当String[]的长度为1时,数组中只存储了解码出的字符串
//dfs函数的意思:对字符串s从i往后的子串进行解码,并存在数组里;
必要的时候还会在数组里存子串最后那个']'的下标
private String[] dfs(String s, int i){
StringBuilder res = new StringBuilder();
//multi为k[encoded_string]的k,是一个正整数
int multi = 0;
while (i < s.length()){
//当前字符为数字,需要更新multi的值
//为啥要乘10?因为是从左往右扫描的,
如果k不是个位数而是n位整数的话就要通过不停的乘10来更新值
if (s.charAt(i) >= '0' && s.charAt(i) <= '9')
multi = 10 * multi + Integer.parseInt(String.valueOf(s.charAt(i)));
//当前字符为'[',此时需要递归地去解码'['后面的子串
else if (s.charAt(i) == '['){
//子串从'['的下一位开始,用tmp保存解码的结果和子串最后的']'在s中的下标
String[] tmp = dfs(s, i + 1);
//更新i的值,由于在上一行的递归中子串以及子串内部的子串都被求出来了,
所以在外层就不用管它们了,直接把i跳到tmp[0]表示的位置
i = Integer.parseInt(tmp[0]);
//这个while循环达到了把k[encoded_string]内的
encoded_string在res后拼接k次的效果(这里的encoded_string就是tmp[1])
while (multi > 0){
res.append(tmp[1]);
multi--;
}
}
//当前字符为']',返回这个子串结尾处的下标和其解码结果
else if (s.charAt(i) == ']'){
return new String[] {String.valueOf(i), res.toString()};
}
//当前字符为非数字、非'['']',则把它拼接到res后
else {
res.append(String.valueOf(s.charAt(i)));
}
//i后移
i++;
}
return new String[] {res.toString()};
}
}