LeetCode 394:字符串解码 Decode String

简介: 题目:给定一个经过编码的字符串,返回它解码后的字符串。Given an encoded string, return its decoded string.编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。

题目:

给定一个经过编码的字符串,返回它解码后的字符串。
Given an encoded string, return its decoded string.

编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。
The encoding rule is: k[encoded_string], where the encoded_string inside the square brackets is being repeated exactly k times. Note that k is guaranteed to be a positive integer.

你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。
You may assume that the input string is always valid; No extra white spaces, square brackets are well-formed, etc.

此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a2[4] 的输入。
Furthermore, you may assume that the original data does not contain any digits and that digits are only for those repeat numbers, k. For example, there won't be input like 3a or 2[4].

示例:

s = "3[a]2[bc]", 返回 "aaabcbc".
s = "3[a2[c]]", 返回 "accaccacc".
s = "2[abc]3[cd]ef", 返回 "abcabccdcdcdef".

解题思路:

​ 这道题类似我们之前做过的一道题:有效的括号: https://mp.weixin.qq.com/s/Sm1S26EgR-dC75hrhVnZGQ

只不过''有效的括号'' [] 内多了一些字符串需要操作。我们同样可以用数据结构栈来解题,,能用栈解决的题目大部分都可以用递归解决,两者逻辑基本相同:

输入:'3[a2[c]]'
初始化栈: 栈nums 存要重复的次数k,栈str 存字符串

遍历字符串:
指针指向字符'3',为数字
num暂存数字3

继续遍历,遇到字符'['
循环次数num入栈nums,空字符串res入栈str
nums: 3        res: ''
num置为0,str置空

继续遍历,遇到字符'a',为字母
空字符串res拼接字母'a',res='a'

继续遍历,遇到字符'2',为数字
num暂存数字2

继续遍历遇到字符'['
num入栈nums,res入栈str
nums: 3 -> 2    str: '' -> 'a'
num置为0,str置空

继续遍历,遇到字符'c',为字母
空字符串res拼接字母'c',res='c'

继续遍历遇到字符']'
nums弹出栈顶元素:当前字符串重复次数2
res = res*2 = 'cc'
str弹出栈顶元素'a'与res拼接并入栈:
res = 'a'+'cc'='acc'
str: '' -> 'acc'

继续遍历遇到字符']'
nums弹出栈顶元素:当前字符串重复次数3
res = res*3 = 'accaccacc'
str弹出栈顶元素空字符串''与res拼接并入栈:
res=''+'accaccacc'='accaccacc'
str: 'accaccacc'

结束返回res

注意:

  • 由于重复次数可能大于10,所以暂存数字时要适当处理,如 num*10+当前数字
  • 在c++里可以直接修改拼接字符,但Java不支持运算符重载,可以借助 StringBuilder 或 StringBuffer 类。
  • 用栈暂存的逻辑与递归基本一致,可以理解为用递归实现栈。
  • python没有栈这种数据结构,可以用 list() 数组或双端队列 deque()
  • python可以只用一个栈以元组的形式重复次数和字符串,如(num,res)

利用栈:

Java:

class Solution {
    public String decodeString(String s) {
        //初始化数据结构
        Stack<StringBuilder> str = new Stack<>();
        Stack<Integer> nums = new Stack<>();
        StringBuilder res = new StringBuilder();
        int num = 0;
        for (char c : s.toCharArray()) {//递归字符串
            if (c == '[') {
                str.push(res);//入栈
                nums.push(num);
                num = 0;//刷新num、res
                res = new StringBuilder();
            } else if (c == ']') {
                StringBuilder tmp = new StringBuilder();
                for (int i = nums.pop(); i > 0; i--) tmp.append(res);//res*3
                res = str.pop().append(tmp);
            } else if (c >= '0' && c <= '9') num = num * 10 + (c - '0');//计算重复次数
            else res.append(c);
        }
        return res.toString();
    }
}

Python:

可直接操作字符串真的很方便。py里有现成的判断字符串的方法:

  • isdigit() 是否为只包含数字的字符串
  • isalpha() 是否为只包含字母的字符串
class Solution:
    def decodeString(self, s: str) -> str:
        #初始化数据结构
        stack, res, num = [], '', 0
        for c in s:
            if c.isdigit():
                num = num * 10 + int(c)
            elif c.isalpha():
                res += c
            elif c == '[':
                #元组形式入栈
                stack.append((res, num))
                #刷新字符串和重复次数
                res, num = '', 0
            else:
                #如果c==']',弹出字符串和重复次数
                last_str, this_num = stack.pop()
                res = last_str + this_num * res
        return res

利用递归:

Java:

将 s.length() 的值以参数传递,减少重复调用 length() 造成的时间损耗

class Solution {
    private int i = -1;//全局变量i,记录字符数组指针位置
    
    public String decodeString(String s) {
        return dfs(s.toCharArray(), s.length()).toString();
    }
    //递归函数
    private StringBuilder dfs(char[] chars, int len) {
        int num = 0;
        StringBuilder str = new StringBuilder();
        while (++i < len) {
            if (chars[i] >= '0' && chars[i] <= '9')
                num = num * 10 + (chars[i] - '0');
            else if (chars[i] == '[') {
                StringBuilder tmp = dfs(chars, len);//递归调用
                while (--num >= 0) str.append(tmp);//重复字符串res=res*num
                num = 0;
            } else if (chars[i] == ']') return str;
            else str.append(chars[i]);
        }
        return str;
    }
}

Python:

class Solution:
    i = -1
    #递归函数,可以直接操作字符串就无需再建一个dfs辅助函数
    def decodeString(self, s: str) -> str:
        res, num = '', 0
        while self.i < len(s) - 1:
            self.i += 1
            if s[self.i].isdigit():
                num = num * 10 + int(s[self.i])
            elif s[self.i].isalpha():
                res += s[self.i]
            elif s[self.i] == '[':
                #递归调用
                res += self.decodeString(s) * num
                num = 0
            elif s[self.i] == ']':
                return res
        return res

欢迎关注微.信公.众号:爱写Bug

目录
相关文章
|
28天前
|
Python
Python中的f-string:更简洁的字符串格式化
Python中的f-string:更简洁的字符串格式化
202 92
|
2月前
|
自然语言处理 Java Apache
在Java中将String字符串转换为算术表达式并计算
具体的实现逻辑需要填写在 `Tokenizer`和 `ExpressionParser`类中,这里只提供了大概的框架。在实际实现时 `Tokenizer`应该提供分词逻辑,把输入的字符串转换成Token序列。而 `ExpressionParser`应当通过递归下降的方式依次解析
198 14
|
5月前
|
Go 索引
【LeetCode 热题100】394:字符串解码(详细解析)(Go语言版)
本文详细解析了 LeetCode 热题 394:字符串解码。题目要求对编码字符串如 `k[encoded_string]` 进行解码,其中 `encoded_string` 需重复 `k` 次。文章提供了两种解法:使用栈模拟和递归 DFS,并附有 Go 语言实现代码。栈解法通过数字栈与字符串栈记录状态,适合迭代;递归解法则利用函数调用处理嵌套结构,代码更简洁。两者时间复杂度均为 O(n),但递归需注意栈深度问题。文章还总结了解题注意事项及适用场景,帮助读者更好地掌握字符串嵌套解析技巧。
141 6
|
6月前
|
数据处理
鸿蒙开发:ArkTs字符串string
字符串类型是开发中非常重要的一个数据类型,除了上述的方法概述之外,还有String对象,正则等其他的用处,我们放到以后得篇章中讲述。
296 19
|
6月前
|
存储 机器学习/深度学习 缓存
🚀 力扣热题 394:字符串解码(详细解析)(Go语言版)
文章提供了两种解法:栈结构和递归解法。栈解法通过维护数字栈与字符串栈,依次处理 `[` 和 `]`,构造解码结果;递归解法则利用函数调用逐层解析嵌套结构。两者时间复杂度均为 $O(n)$,空间复杂度也为 $O(n)$。栈解法直观易懂,适合初学者;递归解法优雅简洁,适合处理深度嵌套规则。掌握这两种方法,可灵活应对类似问题,提升解题能力。
188 11
|
3月前
|
存储 编译器 C语言
关于string的‘\0‘与string,vector构造特点,反迭代器与迭代器类等的讨论
你真的了解string的'\0'么?你知道创建一个string a("abcddddddddddddddddddddddddd", 16);这样的string对象要创建多少个对象么?你知道string与vector进行扩容时进行了怎么的操作么?你知道怎么求Vector 最大 最小值 索引 位置么?
77 0
|
6月前
|
缓存 安全 Java
《从头开始学java,一天一个知识点》之:字符串处理:String类的核心API
🌱 **《字符串处理:String类的核心API》一分钟速通!** 本文快速介绍Java中String类的3个高频API:`substring`、`indexOf`和`split`,并通过代码示例展示其用法。重点提示:`substring`的结束索引不包含该位置,`split`支持正则表达式。进一步探讨了String不可变性的高效设计原理及企业级编码规范,如避免使用`new String()`、拼接时使用`StringBuilder`等。最后通过互动解密游戏帮助读者巩固知识。 (上一篇:《多维数组与常见操作》 | 下一篇预告:《输入与输出:Scanner与System类》)
142 11