力扣394(java)-字符串解码(中等)

题目:

给定一个经过编码的字符串,返回它解码后的字符串。

编码规则为: 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] 

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/decode-string
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路:

本题是嵌套的括号,需要生成字符串,故利用栈先进后出的特点来解决问题,定义两个栈,一个栈numstack用来存放数字,一个栈restack用来存放字符。

遍历字符串s的每个字符c:

1.当c为数字字符时,将数字字符转换为数字,并取出连续的数字num;

2.当c为字母时,将其放在临时存放字符串的StringBuilder res尾部中;

3.当c为左括号 '['时:

  • 将上一次计算出的数字num压入栈numstack中;
  • 将上一次存放在res中的临时结果压入栈restsack中;
  • 然后重置num和临时res,给下一次遇到 '['使用

4.当c为右括号 ']' 时:

  • 取出上次压入restack中的内容;
  • 计算当前 []中重复的字符串;
  • 进行拼接

5.返回字符串res。

举例: 3[a2[c2[ab]]]  (只是模拟,写的不是很规范)

两个栈numstack和restack, StringBuilder res存储结果

i = 0时,s.charAt(i) = 3, num = 3;

i=1时,s.charAt(i) = '[':

  • 3入栈:numstack = 3
  • restack为空
  • 重置:num = 0,res 为空

i=2时,s.charAt(i) = a,res=(a);

i=3时,s.charAt(i) = 2, num = 2;

i=4时,s.charAt(i) = '[':

  • 2入栈:numstack 为(3,2) 
  • 将res里面的字符加入restack,restack为(a)
  • 重置:num = 0,res 为空

i=5时,s.charAt(i) =c ,res=(c);

i=6时,s.charAt(i) = 2,num=2;

i=7时,s.charAt(i) = '[':

  • 2入栈:numstack为(3,2,2)
  • 将res里面的字符加入restack,restack为(a,c)
  • 重置:num = 0,res 为空

i=8,s.charAt(i) =a,res =(a);

i=9,s.charAt(i) =b,res =(ab);

i=10时,s.charAt(i) = ']':

  • 获取上一个倍数:numstack.pollLast() = 2(2就删除了,numstack只有3,2了);
  • temp中添加两次res:即为abab;
  • 与括号外的c合并就变成res = cabab(restack只有a了);

i=11时,s.charAt(i) = ']':

  • 获取上一个倍数:numstack.pollLast() = 2(2就删除了,numstack只有3);
  • temp中添加两次res:即为cababcabab;
  • 与括号外的a合并就变成res = acababcabab(restack为空了);

i=12时,s.charAt(i) = ']':

  • 获取上一个倍数:numstack.pollLast() = 3(numstack为空了);
  • temp中添加三次res:即为acababcababacababcababacababcabab;
  • restack为空,没法合并了

最终将res转换成字符串"acababcabab acababcababacababcabab"。

代码:

 1 class Solution {
 2     public String decodeString(String s) {
 3         //定义两个栈用来存放倍数和字符
 4         Deque<Integer> numstack = new ArrayDeque<>();
 5         Deque<StringBuilder> restack = new ArrayDeque<>();
 6         //拼接数字
 7         int num = 0;
 8         //存放结果
 9         StringBuilder res = new StringBuilder();
10 
11         for(char c : s.toCharArray()){
12             //遇到数字就压入数字栈
13             if(c >= '0' && c <= '9'){
14                 //取出连续的数字
15                 num = num * 10 + c - '0';
16             }else if(c == '['){
17                 //遇到左括号
18                 //将上次计算出的数字压栈
19                 numstack.addLast(num);
20                 //将上一次的倍数后的结果字符存入字符栈
21                 restack.addLast(res);
22                 //重置数字和结果
23                 num = 0;
24                 res = new StringBuilder();
25             }else if(c == ']'){
26                 StringBuilder temp = new StringBuilder();
27                 //获取倍数
28                 int count = numstack.pollLast();
29                 //进行循环当前字符,拼接到上一次结果中
30                 for(int i = 0; i < count; i++){
31                    temp.append(res);
32                 }
33                 //与括号外的合并
34                 res = restack.pollLast().append(temp);
35             }else{
36                 res.append(c);
37             }
38         }
39         return res.toString();
40     }
41 }

 

posted on 2022-09-09 14:05  我不想一直当菜鸟  阅读(134)  评论(0编辑  收藏  举报