LeetCode 394. 字符串解码

394. 字符串解码

    

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

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

利用栈先进后出的性质,使用两个栈来分别保存【每一层所出现的子串】及【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
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值