题目链接

LeetCode

题目描述

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

编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。

你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。

此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a2[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. 构建辅助栈 stack, 遍历字符串 s 中每个字符 c
    • c 为数字时,将数字字符转化为数字 multi,用于后续倍数计算;
    • c 为字母时,在 res 尾部添加 c
    • c[ 时,将当前 multires 入栈,并分别置空置 0:
      • 记录此 [ 前的临时结果 res 至栈,用于发现对应 ] 后的拼接操作;
      • 记录此 [ 前的倍数 multi 至栈,用于发现对应 ] 后,获取 multi × [...] 字符串。
      • 进入到新 [ 后,resmulti 重新记录。
    • c] 时,stack 出栈,拼接字符串 res = last_res + cur_multi * res,其中:
      • last_res是上个 [ 到当前 [ 的字符串,例如 "3[a2[c]]" 中的 a
      • cur_multi是当前 [] 内字符串的重复倍数,例如 "3[a2[c]]" 中的 2
  2. 返回字符串 res
    1. class Solution {
    2. public String decodeString(String s) {
    3. // 记录结果 last_res
    4. StringBuilder ans = new StringBuilder();
    5. // 记录倍数
    6. Deque<Integer> mutilStack = new LinkedList<>();
    7. // 记录字符串
    8. Deque<StringBuilder> ansStack = new LinkedList<>();
    9. // 倍数
    10. int mutil = 0;
    11. for(char c : s.toCharArray()){
    12. // 如果是数字,则说明是倍数(下一个[]的倍数),记录倍数
    13. if(Character.isDigit(c)){
    14. mutil = mutil * 10 + (c - '0');
    15. // [ 表示当前为一个新的需要解码的字符串,先将之前的字符串和
    16. // 倍数(下一个[]的倍数)存到栈中,从新记录
    17. }else if(c == '['){
    18. ansStack.push(ans);
    19. mutilStack.push(mutil);
    20. ans = new StringBuilder();
    21. mutil=0;
    22. // ] 表示当前字符串结束,可以解码
    23. }else if(c == ']'){
    24. // 倍数前面的 字符串
    25. StringBuilder ansTmp = ansStack.poll();
    26. // 当前 字符串 需要的倍数
    27. int mutilTmp = mutilStack.poll();
    28. for(int i = 0; i < mutilTmp; ++i){
    29. ansTmp.append(ans);
    30. }
    31. // 当前结果
    32. ans = ansTmp;
    33. }else{
    34. ans.append(c);
    35. }
    36. }
    37. return ans.toString();
    38. }
    39. }
  • 时间复杂度 O(n)
  • 空间复杂度 O(n)

    方法二:递归

  1. class Solution {
  2. String s;
  3. public String decodeString(String s) {
  4. this.s = s;
  5. return recur(0, s.length() - 1);
  6. }
  7. private String recur(int pos, int right){
  8. if(pos > right){
  9. return "";
  10. }
  11. String res = "";
  12. int left;
  13. // 当前是字符串
  14. if(s.charAt(pos) >='a' && s.charAt(pos) <='z'){
  15. left = pos;
  16. while(pos <= right && s.charAt(pos) >='a' && s.charAt(pos) <='z'){
  17. ++pos;
  18. }
  19. res += s.substring(left, pos);
  20. }
  21. // 当前是倍数
  22. int n = 0;
  23. while(pos <= right && s.charAt(pos) >= '0' && s.charAt(pos) <= '9'){
  24. n = n * 10 + s.charAt(pos) - '0';
  25. ++pos;
  26. }
  27. ++pos;
  28. int l = 1, r = 0;
  29. left = pos;
  30. // 当前倍数范围
  31. while(pos <= right && l != r){
  32. if(s.charAt(pos) == '['){
  33. ++l;
  34. }else if(s.charAt(pos) == ']'){
  35. ++r;
  36. }
  37. ++pos;
  38. }
  39. // 返回结果为当前字符串 + 递归解析当前倍数 + 递归解析当前倍数后面的字符串
  40. return res + recur(left, pos - 2).repeat(n) + recur(pos, right);
  41. }
  42. }
  • 时间复杂度 O(n)
  • 空间复杂度 O(n)