DailyChallenge
394. 字符串解码
20200528
难度:中等
题目描述
给定一个经过编码的字符串,返回它解码后的字符串。
编码规则为: 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".
Solution
[x] 思路一:
LinkedList模拟栈可能会涉及到括号里嵌套了括号的情况,用栈来完成。想到了这道题20. 有效的括号
遇到数字,入栈(这里注意数字可能有多位,比如"100[leetcode]",是把这整个数字入栈)
遇到左括号或者字母,入栈
遇到右括号时,开始出栈,直到
'['为止。出栈后的顺序和原来字符串里的反了,所以翻转一下。由于左括号前一定是数字(代表括号里子字符串的次数),将翻转后的序列根据次数拼接得到新的子字符串并入栈,这样一个k[]的子串就构建好了放在 stack 里原字符串遍历完成后,此时栈中的元素从底到顶遍历拼接,得到答案。
class Solution {
public String decodeString(String s) {
LinkedList<String> stack = new LinkedList<>();
int i = 0;
while(i < s.length()){
char c = s.charAt(i);
if(Character.isDigit(c)){
//数字入栈,注意数字可能有多位,比如"100[leetcode]"
String number = "";
while(Character.isDigit(s.charAt(i))){
number += String.valueOf(s.charAt(i++));
}
stack.addLast(number);
}else if(Character.isLetter(c) || c == '['){
//字母或者左括号,入栈
stack.addLast(String.valueOf(c));
i++;
}else{
//到']'的时候,开始出栈,直到'[',左括号前一定是数字
i++;
List<String> list = new ArrayList<>();
while(!"[".equals(stack.peekLast())){
list.add(stack.removeLast());
}
// 翻转顺序
Collections.reverse(list);
// 左括号出栈
stack.removeLast();
// 左括号前面试数字,代表里面出现的次数
int count = Integer.parseInt(stack.removeLast());
// String sub = String.join(",", list);
// List to String
String sub = "";
for(String s_list : list){
sub += s_list;
}
String subsub = sub;
while(count > 1){
sub += subsub;
count--;
}
//构造出来的字符串入栈
stack.addLast(sub);
}
}
// 从底往上遍历栈,返回答案
String res = "";
for(String s_stack : stack){
res += s_stack;
}
return res;
}
}
Tips:
用
LinkedList而不是Stack就是为了方便最后栈中的元素从底到顶遍历拼接[ ] 思路二:递归
将
[和]分别作为递归的开启与终止条件。- 当
s[i] == ']'时,返回当前括号内记录的res字符串与]的索引i(更新上层递归指针位置); - 当
s[i] == '['时,开启新一层递归,记录此[...]内字符串tmp和递归后的最新索引i,并执行res + multi * tmp拼接字符串。 - 遍历完毕后返回
res。
class Solution { public String decodeString(String s) { return dfs(s, 0)[0]; } private String[] dfs(String s, int i) { StringBuilder res = new StringBuilder(); int multi = 0; while(i < s.length()) { if(s.charAt(i) >= '0' && s.charAt(i) <= '9') multi = multi * 10 + Integer.parseInt(String.valueOf(s.charAt(i))); else if(s.charAt(i) == '[') { String[] tmp = dfs(s, i + 1); i = Integer.parseInt(tmp[0]); while(multi > 0) { res.append(tmp[1]); multi--; } } else if(s.charAt(i) == ']') return new String[] { String.valueOf(i), res.toString() }; else res.append(String.valueOf(s.charAt(i))); i++; } return new String[] { res.toString() }; } }- 当
本文使用 mdnice 排版