LeetCode 394. 字符串解码

简介: LeetCode 394. 字符串解码

 394. 字符串解码

   

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

编码规则为: 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 <= s.length <= 30
  • s 由小写英文字母、数字和方括号 '[]' 组成
  • s 保证是一个 有效 的输入。
  • s 中所有整数的取值范围为 [1, 300]


思路:参考 LeetCode题解

利用的先进后出,来间接保存 【每一层所出现的子串】及 【k所对应的重复次数栈】

    • 初始化两个栈:每一层的【字符串栈】和【k所对应的重复次数栈】
    • 遍历题目给定的字符串s,并判断字符char是 “数字” or “左方括号” or “右方括号” or “字母
      • 数字 '0' ~ '9':因为每一层k所对应的重复次数 有可能是单倍或数十倍(比如重复1次或11次),所以需要遍历完当前层出现的完整重复次数(完整倍数)num = num*10 + n例如:11ab,先遍历到第一个字符 '1' 得到 num = 0*10 + 1 = 1,然后继续遍历第二个字符 '1' 从而得到 num = 1*10 + 1 = 11 ... 这里的 11ab 也就表示 ab重复出现11次。
      • 左方括号 [:将上一层的result和num分别入栈保存,并清空重置对应记录,避免干扰下一层统计
      • 右方括号 ]:此时说明内层已经从左 '[' 至右 ']' 遍历完成了,那么可以借助栈中数据来组装内层数据了。

        在strStack栈中保存的外层子串 + 内层子串*在numStack栈中保存的内层重复次数,result = topStr + strings.Repeat(result, topNum)

        这里要注意:内层子串的重复次数是由方括号外的外层数字来最终决定的。
      • 字母 'a' ~ 'z':不断追加每层的result结果即可 ~

        时间复杂度

        记解码后得出的字符串长度为 S除了遍历一次原字符串 s,我们还需要将解码后的字符串中的每个字符都入栈,并最终拼接进答案中,故渐进时间复杂度为 O(S+∣s∣),即 O(S)。


        空间复杂度

        记解码后得出的字符串长度为 S,这里用栈维护 TOKEN,栈的总大小最终与 S 相同,故渐进空间复杂度为 O(S)。

        // 参考:https://leetcode.cn/problems/decode-string/solutions/264879/zhan-de-ji-yi-nei-ceng-de-jie-ma-liao-bie-wang-lia/?languageTags=golang
        func decodeString(s string) string {
            // 初始化每一层的【字符串栈】和【k所对应的重复次数栈】
            strStack, numStack := []string{}, []int{}
            result, num := "", 0
            for _, char := range s {
                if char >= '0' && char <= '9' {
                    // 获取每一层要重复的次数:例如 12[ab],那么就需要获取到12(1*10+2)这个完整的数字
                    n, _ := strconv.Atoi(string(char))
                    num = num*10 + n
                } else if char == '[' {
                    // 将上一层的result和num分别入栈保存,并清空对应记录,避免干扰下一层统计
                    strStack = append(strStack, result)
                    result = ""
                    numStack = append(numStack, num)
                    num = 0
                } else if char == ']' {
                    // 组装每一层字符串数据
                    topStr := strStack[len(strStack)-1]     // get top value
                    strStack = strStack[:len(strStack)-1]   // pop
                    topNum := numStack[len(numStack)-1]     // get top value
                    numStack = numStack[:len(numStack)-1]   // pop
                    // 外层子串 + 内层子串*内层子串重复次数
                    result = topStr + strings.Repeat(result, topNum)
                } else {
                    // 不断追加每层的result结果:例如ab[...],那么就要拼接获取到这一层ab这个完整的字符串
                    result += string(char)
                }
            }
            return result
        }

        image.gif


        目录
        相关文章
        |
        3月前
        |
        JavaScript
        力扣3333.找到初始输入字符串Ⅱ
        【10月更文挑战第9天】力扣3333.找到初始输入字符串Ⅱ
        40 1
        |
        3月前
        |
        C++
        Leetcode第43题(字符串相乘)
        本篇介绍了一种用C++实现的字符串表示的非负整数相乘的方法,通过逆向编号字符串,将乘法运算转化为二维数组的累加过程,最后处理进位并转换为字符串结果,解决了两个大数相乘的问题。
        30 9
        |
        3月前
        |
        算法 C++
        Leetcode第八题(字符串转换整数(atoi))
        这篇文章介绍了LeetCode上第8题“字符串转换整数(atoi)”的解题思路和C++的实现方法,包括处理前导空格、正负号、连续数字字符以及整数溢出的情况。
        24 0
        |
        3月前
        【LeetCode 22】459.重复的子字符串
        【LeetCode 22】459.重复的子字符串
        33 0
        |
        3月前
        【LeetCode 20】151.反转字符串里的单词
        【LeetCode 20】151.反转字符串里的单词
        25 0
        |
        3月前
        【LeetCode 19】541.反转字符串II
        【LeetCode 19】541.反转字符串II
        25 0
        |
        3月前
        【LeetCode 18】6.2.反转字符串
        【LeetCode 18】6.2.反转字符串
        19 0
        |
        5月前
        |
        存储 算法
        LeetCode第43题字符串相乘
        LeetCode第43题"字符串相乘"的解题方法,通过使用数组存储乘积并处理进位,避免了字符串转换数字的复杂性,提高了算法效率。
        LeetCode第43题字符串相乘
        |
        5月前
        |
        算法 Java
        LeetCode第28题找出字符串中第一个匹配项的下标
        这篇文章介绍了LeetCode第28题"找出字符串中第一个匹配项的下标"的两种解法:暴力解法和KMP算法,并解释了KMP算法通过构建前缀表来提高字符串搜索的效率。
        LeetCode第28题找出字符串中第一个匹配项的下标
        |
        5月前
        |
        算法
        LeetCode第8题字符串转换整数 (atoi)
        该文章介绍了 LeetCode 第 8 题字符串转换整数 (atoi)的解法,需要对字符串进行格式解析与校验,去除前导空格和处理正负号,通过从高位到低位的计算方式将字符串转换为整数,并处理越界情况。同时总结了这几道题都需要对数字的表示有理解。
        LeetCode第8题字符串转换整数 (atoi)