今天的题目来源于 leetcode 第 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] 二、题目解析 注意示例 2 ,可以发现字符串中存在括号内有嵌套括号的情况,这个时候,只有先把内层括号解码成功,才能再去解码外层括号。
也就意味着后面访问的括号比前面访问的括号还更早的进行处理,与栈的先入后出特点对应。
所以,本题使用栈来处理。
具体操作如下:
1、构建两个栈,一个是数字栈 numstack ,在遍历编码字符串过程中记录出现的数字;一个是字符串栈 strstack ,在遍历编码字符串过程中记录出现的字符串。
2、初始化两个变量,一个是 digit ,用来记录访问到字符串之前出现的数字;一个是 res ,在访问编码字符串的过程中,把得到的结果存放到 res 中。
3、接下来,开始从头到尾访问编码字符串,在访问过程中,字符会出现 4 种情况。
4、如果是数字,需要把字符转成整型数字,然后更新到 digit 上,代表后续的字符串需要重复 digit 次。
5、如果是字符,说明它就出现一次,可以直接存放到 res 中。
6、如果是[ ,这个时候出现了嵌套的内层编码字符串,而外层的解码需要等待内层解码的结果,那么之前已经扫描的字符需要存放起来,等到内层解码之后再重新使用。
7、如果是] ,此时,内层解码已经有结果,需要把它和前面的字符串进行拼接。
8、拼接的方式就是先通过 numsstack 的栈顶元素获取重复的次数,再通过 strstack 的栈顶元素获取前面的字符串。
9、最后返回 res 就行。
三、参考代码 1、java 代码 // 登录 algomooc 官网获取更多算法图解// https://www.algomooc.com// 作者:程序员吴师兄// 代码有看不懂的地方一定要私聊咨询吴师兄呀// 字符串解码(leetcode 394)//leetcode.cn/problems/decode-string/class solution { public string decodestring(string s) { // 创建数字栈,在遍历编码字符串过程中记录出现的数字 deque numstack = new linkedlist(); // 创建字符栈,在遍历编码字符串过程中记录出现的字符串 deque strstack = new linkedlist(); // 在访问编码字符串的过程中,用来记录访问到字符串之前出现的数字,一开始为 0 int digit = 0; // 在访问编码字符串的过程中,把得到的结果存放到 res 中 stringbuilder res = new stringbuilder(); // 从头到尾遍历编码字符串 for (int i = 0; i = 'a' && ch <= 'z') ){ // 说明它就出现一次,可以直接存放到 res 中 res.append(ch); // 3、如果是[ // 出现了嵌套的内层编码字符串,而外层的解码需要等待内层解码的结果 // 那么之前已经扫描的字符需要存放起来,等到内层解码之后再重新使用 }else if (ch == '[') { // 把数字存放到数字栈 numstack.push(digit); // 把外层的解码字符串存放到字符串栈 strstack.push(res); // 开始新的一轮解码 // 于是,digit 归零 digit = 0; // res 重新初始化 res = new stringbuilder(); // 4、如果是] }else if (ch == ']') { // 此时,内层解码已经有结果,需要把它和前面的字符串进行拼接 // 第一步,先去查看内层解码的字符串需要被重复输出几次 // 比如 e3[abc],比如内层解码结果 abc 需要输出 3 次 // 通过数字栈提取出次数 int count = numstack.poll(); // 第二步,通过字符串栈提取出之前的解码字符串 stringbuilder outstring = strstack.poll(); // 第三步,不断的把内层解码的字符串拼接起来 for (int j = 0; j < count; j++) { // 拼接到 outstring 后面,拼接 count 次 outstring.append(res.tostring()); } // 再把此时得到的结果赋值给 res res = outstring; } } // 返回解码成功的字符串 return res.tostring(); }} 2、c++ 代码 class solution {public: string decodestring(string s) { // 创建数字栈,在遍历编码字符串过程中记录出现的数字 stack numstack; // 创建字符栈,在遍历编码字符串过程中记录出现的字符串 stack strstack; // 在访问编码字符串的过程中,用来记录访问到字符串之前出现的数字,一开始为 0 int digit = 0; // 在访问编码字符串的过程中,把得到的结果存放到 res 中 string res; // 从头到尾遍历编码字符串 for (int i = 0; i ='0'&&ch= 'a' && ch <= 'z') ){ // 说明它就出现一次,可以直接存放到 res 中 res += ch; // 3、如果是[ // 出现了嵌套的内层编码字符串,而外层的解码需要等待内层解码的结果 // 那么之前已经扫描的字符需要存放起来,等到内层解码之后再重新使用 }else if (ch == '[') { // 把数字存放到数字栈 numstack.push(digit); // 把外层的解码字符串存放到字符串栈 strstack.push(res); // 开始新的一轮解码 // 于是,digit 归零 digit = 0; // res 重新初始化 res = ; // 4、如果是] }else if (ch == ']') { // 此时,内层解码已经有结果,需要把它和前面的字符串进行拼接 // 第一步,先去查看内层解码的字符串需要被重复输出几次 // 比如 e3[abc],比如内层解码结果 abc 需要输出 3 次 // 通过数字栈提取出次数 int count = numstack.top(); numstack.pop(); // 第二步,通过字符串栈提取出之前的解码字符串 string outstring = strstack.top(); strstack.pop(); // 第三步,不断的把内层解码的字符串拼接起来 for (int j = 0; j str: # 创建数字栈,在遍历编码字符串过程中记录出现的数字 numstack = [] # 创建字符栈,在遍历编码字符串过程中记录出现的字符串 strstack = [] # 在访问编码字符串的过程中,用来记录访问到字符串之前出现的数字,一开始为 0 digit = 0 # 在访问编码字符串的过程中,把得到的结果存放到 res 中 res = # 从头到尾遍历编码字符串 for ch in s: # 在遍历过程中,字符会出现 4 种情况 # 先获取此时访问的字符 # 1、如果是数字,需要把字符转成整型数字 # 注意数字不一定是 1 位,有可能是多位 # 比如 123a,在字母 a 的前面出现了 123,表示 a 重复出现 123 次 # 那么一开始 ch 为 1,当访问到 ch 为 2 的时候,1 和 2 要组成数字 12 # 再出现 3 ,12 和 3 组成数字 123 if '0' <= ch = 'a' and ch <= 'z': # 说明它就出现一次,可以直接存放到 res 中 res += ch # 3、如果是[ # 出现了嵌套的内层编码字符串,而外层的解码需要等待内层解码的结果 # 那么之前已经扫描的字符需要存放起来,等到内层解码之后再重新使用 elif ch == '[' : # 把数字存放到数字栈 numstack.append(digit) # 把外层的解码字符串存放到字符串栈 strstack.append(res) # 开始新的一轮解码 # 于是,digit 归零 digit = 0 # res 重新初始化 res = # 4、如果是] elif ch == ']': # 此时,内层解码已经有结果,需要把它和前面的字符串进行拼接 # 第一步,先去查看内层解码的字符串需要被重复输出几次 # 比如 e3[abc],比如内层解码结果 abc 需要输出 3 次 # 通过数字栈提取出次数 count = numstack.pop() # 第二步,通过字符串栈提取出之前的解码字符串 outstring = strstack.pop() # 第三步,不断的把内层解码的字符串拼接起来 for j in range(0,count) : # 拼接到 outstring 后面,拼接 count 次 outstring += res # 再把此时得到的结果赋值给 res res = outstring # 返回解码成功的字符串 return res 四、复杂度分析 时间复杂度 o(n),一次遍历 s 空间复杂度 o(n),辅助栈在极端情况下需要线性空间。
微软重大改变!Windows10将每年进行两次大更新!
配电网组成及特点/体系结构/SCADA系统
华为Mate9成首款搭载Alexa语音助手的安卓机
电机控制器中PSoC的探究与应用
如何在Linux使用unzip命令合并解压分卷文件
LeetCode 394:字符串解码
Verilog是编程语言吗
乘虚而入,日本半导体企业加紧布局中国
少了华为,美国能否搞好5G?
爆料称微软Win10 2021年版本将支持原生运行安卓App
8 种进行简单线性回归的方法分析与讨论
你对于5G贷了解吗
国内大型植保无人机TDN-01问世,推动三农的稳步发展
Molex Mini-Fit Sigma连接器产品介绍
网站被攻击导致服务器无法访问的终极解决办法
国内首款支持直播的标准卫星解码芯片GK6105S发布
低压成套补偿柜常用投切开关
麒麟a2芯片多少纳米 麒麟a2芯片搭载哪些型号
以CD4511和NE555制作的八路数显抢答器
剪板机的系统组成及参数机能介绍