LeetCode 394:字符串解码 Decode String
题目:
给定一个经过编码的字符串,返回它解码后的字符串。
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 ,例如不会出现像 3a
或 2[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

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
深入浅出 Java 虚拟机 是你通往高级 Java 开发的必经之路
干货来咯 前言: 今天要给大家分享的是Java虚拟机的一些硬货知识,文章不错的话记得给我点给个关注哦,私信我可以获取更多的java资料。 **第一章 JVM 内存模型**Java 虚拟机(Java Virtual Machine=JVM)的内存空间分为五个部分,分别是: 程序计数器Java 虚拟机栈本地方法栈堆方法区。下面对这五个区域展开深入的介绍。 1.1 程序计数器 1.1.1 什么是程序计数器? 程序计数器是一块较小的内存空间,可以把它看作当前线程正在执行的字节码的行号指示器。也就是说,程序计数器里面记录的是当前线程正在执行的那一条字节码指令的地址。 注:但是,如果当前线程正在执行的是一个本地方法,那么此时程序计数器为空。 1.1.2 程序计数器的作用 程序计数器有两个作用: 字节码解释器通过改变程序计数器来依次读取指令,从而实现代码的流程控制,如:顺序执行、选择、循环、异常处理。在多线程的情况下,程序计数器用于记录当前线程执行的位置,从而当线程被切换回来的时候能够知道该线程上次运行到哪儿了。1.1.3 程序计数器的特点 是一块较小的存储空间线程私有。每条线程都有一个程序计数器。...
- 下一篇
wordpress 内容备份镜像站点建立方法及注意事项
作为虾米级站长一枚,实则是不懂代码的菜鸟,由于自己的站点是小水管主机,而且稳定性也难以保障,在很多访客的建议下,也想建立一个内容镜像站点,以实现当主站的主机维护时,能够有一个备用站点让访客访问。 最先我是想能够有一个共用的数据库可以给两个站点一起使用,但百度查了资料后,发现这对于虚拟主机建站来说好像不适用。 直到找到了以下的代码,可以实现源站发表文章时,自动在镜像站点也发表出来。 第一步,在镜像站根目录创建一个命名为 post.php 的 php 文件,代码内容: //以下为代码正文… <?php //文章接收 define('WP_USE_THEMES', false); require_once("wp-load.php"); $key='123456'; //设置启动 API 的密钥 if($_POST['key']==$key){ $categorys=explode(',',$_POST['category']); $category=array(); for($x=1;$x<count($categorys);$x++) { $category[$x-1]=ge...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS关闭SELinux安全模块
- CentOS7安装Docker,走上虚拟化容器引擎之路
- Docker安装Oracle12C,快速搭建Oracle学习环境
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- Linux系统CentOS6、CentOS7手动修改IP地址
- Hadoop3单机部署,实现最简伪集群
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- CentOS7,8上快速安装Gitea,搭建Git服务器