大家好!我是曾续缘💘
今天是《LeetCode 热题 100》系列
发车第 71 天
栈第 3 题
❤️点赞 👍 收藏 ⭐再看,养成习惯
给定一个经过编码的字符串,返回它解码后的字符串。
编码规则为:
k[encoded_string]
,表示其中方括号内部的encoded_string
正好重复k
次。注意k
保证为正整数。你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。
此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数
k
,例如不会出现像3a
或2[4]
的输入。示例 1:
输入:s = "3[a]2[bc]" 输出:"aaabcbc"示例 2:
输入:s = "3[a2[c]]" 输出:"accaccacc"示例 3:
输入:s = "2[abc]3[cd]ef" 输出:"abcabccdcdcdef"示例 4:
输入:s = "abc3[cd]xyz" 输出:"abccdcdcdxyz"提示:
难度:💖💖
1 <= s.length <= 30
s
由小写英文字母、数字和方括号'[]'
组成s
保证是一个 有效 的输入。s
中所有整数的取值范围为[1, 300]
解题方法
给定的字符串是一段已经按照某种规则编码过的文本,我们的任务是解析这段文本,得到解码后的字符串。
这个问题可以用栈来解决。我们遍历给定的编码字符串,根据不同的字符类型,将它们放入栈中。
- 当遇到数字时,我们把数字作为重复次数放入栈中。
- 当遇到字母或左括号时,我们把字母或左括号作为字符放入栈中。
- 当遇到右括号时,说明一个编码单元结束了,我们需要解析这个编码单元。我们先从栈中弹出字符串,翻转弹出的字符串,再弹出重复次数,将字符串重复对应的次数,然后把结果重新放入栈中。
这样,我们遍历完整个字符串后,栈中就只剩下了解码后的字符串。
Code
查看代码
java
class Solution {
public String decodeString(String s) {
// 创建一个链表形式的栈,用于存储字符串、数字和临时字符串
LinkedList<String> stk = new LinkedList<String>();
int i = 0;
while(i < s.length()){
char cur = s.charAt(i);
if(Character.isDigit(cur)){
// 遇到数字,构建一个数字字符串
StringBuilder digit = new StringBuilder();
while (Character.isDigit(s.charAt(i))) {
digit.append(s.charAt(i++));
}
// 把数字字符串放入栈中
stk.addLast(digit.toString());
}else if(Character.isLetter(cur) || cur == '['){
// 遇到字母或左括号,直接把它们放入栈中
stk.addLast(String.valueOf(s.charAt(i++)));
}else{
// 遇到右括号,解析括号内的编码单元
i++; // 跳过右括号
LinkedList<String> tmp = new LinkedList<String>();
while(!"[".equals(stk.peekLast())){
tmp.addLast(stk.removeLast()); // 弹出栈中的字符,直到遇到左括号
}
// 翻转括号内的编码单元
Collections.reverse(tmp);
// 弹出左括号
stk.removeLast();
// 弹出栈中的重复次数
int repeat = Integer.parseInt(stk.removeLast());
// 构建一个临时字符串,用于存放重复的字符串
StringBuilder sb = new StringBuilder();
StringBuilder one = new StringBuilder();
for (String t : tmp) {
one.append(t);
}
// 将字符串重复对应的次数,并放入栈中
while(repeat-- > 0){
sb.append(one);
}
stk.addLast(sb.toString());
}
}
// 栈中剩下的就是解码后的字符串
StringBuilder ans = new StringBuilder();
for (String t : stk) {
ans.append(t);
}
return ans.toString();
}
}