当前位置: 首页 > news >正文

【经典面试】87 字符串解码

字符串解码

    • 题解1 递归(程序栈)——形式语言自动机(LL(1)) : O(S)
      • 另一种递归(直观)
    • 题解2 2个栈(逆波兰式)
      • 1个栈(参考官方,但是不喜欢)

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

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

题解1 递归(程序栈)——形式语言自动机(LL(1)) : O(S)

class Solution {int idx;
public:int getdigits(string& s){int ret = 0;while(idx < s.size() && isdigit(s[idx])){ret = ret*10 + s[idx++]-'0';}return ret;} string getstring(string& s){// 结束条件if(idx == s.size() || s[idx] == ']')return string("");// 当前字符char cur = s[idx];// 重复次数置1int rep = 1;// 返回值string ret = "";// condition:如果是数字if(isdigit(cur)){int rep = getdigits(s);string str = "";// 跳左括号idx ++;// 顺序很重要:跳完左括号就要 取后面的stringstr = getstring(s);// 跳右括号idx ++;// 后--while(rep--){ret += str;}}// condition:如果是字母else if(isalpha(cur)){ret = string(1, s[idx++]);}return ret+getstring(s);}string decodeString(string s) {idx = 0;return getstring(s);}
};

在这里插入图片描述

另一种递归(直观)

class Solution {public:string decodeString(string s) {string res = "";for(int i = 0; i < s.size(); i++){// 字符if(s[i]>='a' && s[i] <= 'z'){res += s[i];// 左括号或者数字}else{int rep = 0;while(s[i] >= '0' && s[i] <= '9'){rep = rep*10 + s[i++]-'0';}int curp = i+1;int lnum = 1;while(lnum){i ++; // i最后是下一次解决的一段字符串的结尾([[[..]]],左括号要和右括号数对上)if(s[i] == '[') lnum++;if(s[i] == ']') lnum--;}string str = decodeString(s.substr(curp, i-curp));while(rep --){res += str;}}}return res;}
};

在这里插入图片描述

题解2 2个栈(逆波兰式)

class Solution {public:string decodeString(string s) {stack<int> num_stk; // 数字栈stack<string> str_stk; // 字符串栈string res = ""; // 当前累积的字符串// 逆波兰式for(int i = 0; i < s.size(); i++){if(isdigit(s[i])){int tmp = s[i]-'0';while(isdigit(s[++i]))tmp = tmp*10 + s[i]-'0';num_stk.push(tmp);i --; // for 有自增}else if(s[i] == '['){str_stk.push(res); // 把上一段存起来res = ""; // 清空,开始累积该左括号后面的字符串}else if(s[i] == ']'){string tmp = "";int rep = num_stk.top();num_stk.pop();while(rep--)tmp += res;res = str_stk.top() + tmp;str_stk.pop();}else{res += s[i]; }}return res;}
};

在这里插入图片描述

1个栈(参考官方,但是不喜欢)

class Solution {
public:string getDigits(string &s, size_t &ptr) {string ret = "";while (isdigit(s[ptr])) {ret.push_back(s[ptr++]);}return ret;}string getString(vector <string> &v) {string ret;for (const auto &s: v) {ret += s;}return ret;}string decodeString(string s) {vector <string> stk;size_t ptr = 0;while (ptr < s.size()) {char cur = s[ptr];if (isdigit(cur)) {// 获取一个数字并进栈string digits = getDigits(s, ptr);stk.push_back(digits);} else if (isalpha(cur) || cur == '[') {// 获取一个字母并进栈stk.push_back(string(1, s[ptr++])); } else {++ptr;vector <string> sub;while (stk.back() != "[") {sub.push_back(stk.back());stk.pop_back();}// sub push的顺序是逆序,累积前需要反过来reverse(sub.begin(), sub.end());// 左括号出栈stk.pop_back();// 此时栈顶为当前 sub 对应的字符串应该出现的次数int repTime = stoi(stk.back()); stk.pop_back();string t, o = getString(sub);// 构造字符串while (repTime--) t += o; // 将构造好的字符串入栈stk.push_back(t);}}return getString(stk);}
};

相关文章:

  • yum 命令
  • CSP-S 2023 T1密码锁 T2消消乐
  • RISC-V IDE MRS无感远程协助模块详解
  • 【LeetCode:80. 删除有序数组中的重复项 II | 双指针】
  • Py之auto-gptq:auto-gptq的简介、安装、使用方法之详细攻略
  • SpringCloud中Turbine 1.X版本BUG
  • TensorFlow 的应用场景有哪些
  • Pycharm安装jupyter和d2l
  • Redis与Mysql的数据一致性(双写一致性)
  • 01【保姆级】-GO语言特点 下载安装 hello
  • Python将知网导出的endnote题录转为Refworks模式
  • 计算1到100的和
  • Spring Cloud Alibaba中Nacos的安装(Windows平台)以及服务的发现
  • python中使用websocket调用、获取、保存大模型API
  • 招投标系统简介 企业电子招投标采购系统源码之电子招投标系统 —降低企业采购成本
  • [译] 理解数组在 PHP 内部的实现(给PHP开发者的PHP源码-第四部分)
  • 【跃迁之路】【477天】刻意练习系列236(2018.05.28)
  • 【跃迁之路】【733天】程序员高效学习方法论探索系列(实验阶段490-2019.2.23)...
  • CentOS7简单部署NFS
  • conda常用的命令
  • Create React App 使用
  • css布局,左右固定中间自适应实现
  • css选择器
  • Cumulo 的 ClojureScript 模块已经成型
  • emacs初体验
  • javascript 哈希表
  • java中具有继承关系的类及其对象初始化顺序
  • maven工程打包jar以及java jar命令的classpath使用
  • MYSQL如何对数据进行自动化升级--以如果某数据表存在并且某字段不存在时则执行更新操作为例...
  • MySQL-事务管理(基础)
  • python 学习笔记 - Queue Pipes,进程间通讯
  • spring cloud gateway 源码解析(4)跨域问题处理
  • vue 配置sass、scss全局变量
  • 从0搭建SpringBoot的HelloWorld -- Java版本
  • 第13期 DApp 榜单 :来,吃我这波安利
  • 动手做个聊天室,前端工程师百无聊赖的人生
  • 漫谈开发设计中的一些“原则”及“设计哲学”
  • 少走弯路,给Java 1~5 年程序员的建议
  • 算法系列——算法入门之递归分而治之思想的实现
  • MiKTeX could not find the script engine ‘perl.exe‘ which is required to execute ‘latexmk‘.
  • 你对linux中grep命令知道多少?
  • Linux权限管理(week1_day5)--技术流ken
  • 好程序员大数据教程Hadoop全分布安装(非HA)
  • ​【C语言】长篇详解,字符系列篇3-----strstr,strtok,strerror字符串函数的使用【图文详解​】
  • !!【OpenCV学习】计算两幅图像的重叠区域
  • # 手柄编程_北通阿修罗3动手评:一款兼具功能、操控性的电竞手柄
  • #ifdef 的技巧用法
  • #laravel 通过手动安装依赖PHPExcel#
  • #LLM入门|Prompt#1.8_聊天机器人_Chatbot
  • #我与Java虚拟机的故事#连载01:人在JVM,身不由己
  • (Bean工厂的后处理器入门)学习Spring的第七天
  • (rabbitmq的高级特性)消息可靠性
  • (windows2012共享文件夹和防火墙设置
  • (附源码)spring boot儿童教育管理系统 毕业设计 281442
  • (附源码)springboot 智能停车场系统 毕业设计065415