【算法挑战】字符串解码(含解析、源码)

news2024/11/25 21:50:29

394.字符串解码

https://leetcode-cn.com/problems/decode-string/

  • 394.字符串解码
    • 题目描述
    • 方法 1: 递归
      • 思路
      • 复杂度分析
      • 代码
    • 方法 2: 循环 + 栈
      • 图解
      • 复杂度分析
      • 代码

题目描述

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

编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。

你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。

此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。

示例:

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/decode-string
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

方法 1: 递归

思路

在这里插入图片描述

n[string] 表示解析 [] 模板里面的内容,然后重复 n 次,即得到 n 个 string 拼接起来的字符串。

根据题意,[] 里面也是可以嵌套 [] 的,例如 n[m[string]]。这种情况下,我们得先解析最内层的模板,重复 m 次,然后将 m * string 的结果作为外层模板的解析内容,再重复 n 次。

如果嵌套的层数更多,我们也是得先找到最内层的 [],就像洋葱一样,一层一层地剥开,然后再从内到外一层一层地解析和拼接。这种描述很容易就让人想到了递归。

看代码注释吧。

复杂度分析

  • 时间复杂度: O ( S ) O(S) O(S),S 是解析后字符串的长度。
  • 空间复杂度: O ( S ) O(S) O(S),S 是解析后字符串的长度,递归栈空间。

代码

const type = {
    isAlpha: s => /[a-z]/i.test(s),
    isDigit: s => /[0-9]/.test(s),
    isOpenParen: s => s === '[',
    isCloseParen: s => s === ']',
};

/**
 * @param {string} s
 * @return {string}
 */
var decodeString = function (s, i = 0) {
    // 从 i 开始遍历字符串

    let decoded = ''; // 解密字符串
    let cnt = ''; // 累计次数

    while (i < s.length) {
        if (type.isAlpha(s[i])) {
            // 普通字符,直接拼接到 decoded
            decoded += s[i];
            i++;
        } else if (type.isDigit(s[i])) {
            // 数字,拼接到 cnt
            cnt += s[i];
            i++;
        } else if (type.isOpenParen(s[i])) {
            // 遇到开括号,就把括号内的字符串重复 cnt 次,再拼接到 decoded
            // 但括号内可能存在嵌套括号,所以需要递归处理
            // 我们需要从递归中取两个东西,1.括号内解析后的模式,2.这个开括号对应的右括号的下标,下次遍历字符串就从这个下标+1开始
            const [pattern, nextIndex] = decodeString(s, i + 1);
            // 重复 cnt 次拼接到 decoded
            decoded += pattern.repeat(Number(cnt));

            cnt = '';
            i = nextIndex;
            continue;
        } else if (type.isCloseParen(s[i])) {
            // 遇到闭括号,说明括号内的模式解析完毕
            // 递归结束,返回我们需要的东西:1.解析后的字符串,2.解析到的字符下标
            return [decoded, i + 1];
        }
    }
    return decoded;
};

C++ Code

class Solution {
private:
    int ptr_ = 0;
public:
    string decodeString(string s) {
      string decoded_str = "";
      string repeat_times = "";

      int i = ptr_;
      while (i < s.length()) {
          if (isalpha(s[i])) {
              decoded_str += s[i];
              i++;
          } else if (isdigit(s[i])) {
              repeat_times += s[i];
              i++;
          } else if (s.compare(i, 1, "[") == 0) {
              ptr_ = i + 1;
              string pattern = decodeString(s);
              i = ptr_;
  
              int times = stoi(repeat_times);
              for (int t = 0; t < times; t++) {
                  decoded_str += pattern;
              }
              repeat_times = "";
          } else if (s.compare(i, 1, "]") == 0) {
              ptr_ = i + 1;
              return decoded_str;
          }
      }
      return decoded_str;
    }
};

方法 2: 循环 + 栈

可以用递归解决的问题,也可以用循环来解决。

这里我用了正则 /[a-zA-Z]+|[0-9]+|\[|\]/exec() 方法来遍历字符串并把它们拆分成 token,比如,lz3[ab2[c]] 会被拆分成 lz, 3, [, ab, 2, [, c, ], ]

  1. 遇到字母块 (lz)、数字时,入栈;
  2. 遇到 [ 时,入栈,用来标识当前进入一个模板解析了;
  3. 遇到 ] 时,说明当前模板遍历完了,我们可以开始解析了。开始出栈,把出栈的字母块都拼接起来,等出栈到 [ 时,说明当前模板解析完成了。继续出栈一个元素,这个元素就是当前模板要重复的次数,把"字母块 * 次数"后推入栈中。之所以要推入栈中是因为模板是可以嵌套的,当前模板的外层可以还是一个模板,所以我们要把结果放回去,继续解析外层的模板。

图解

复杂度分析

  • 时间复杂度: O ( S ) O(S) O(S),S 是解析后字符串的长度。
  • 空间复杂度: O ( S ) O(S) O(S),S 是解析后字符串的长度。

代码

/**
 * @param {string} s
 * @return {string}
 */
var decodeString = function (s) {
    const reg = /[a-zA-Z]+|[0-9]+|\[|\]/g;
    const stack = [];
    const peek = () => stack[stack.length - 1]; // p.s. 不正经栈

    while (reg.lastIndex < s.length) {
        let token = reg.exec(s)[0];
        if (token !== ']') {
            // 数字,字母,左括号通通入栈
            stack.push(token);
        } else {
            // 遇到右括号就开始出栈
            let str = '';
            // [] 中间的就是要重复的模式,把它们全部出栈,拼接起来
            while (peek() !== '[') {
                str = stack.pop() + str;
            }
            // 丢掉左括号
            stack.pop();
            // 左括号前面的一定是模式重复的次数
            const num = +stack.pop();
            // 把复制操作后的字符串放回栈中,作为外层 [] 模式的一部分
            stack.push(str.repeat(num));
        }
    }
    return stack.join('');
};

总结

以上就是本文所有内容了,希望能对你有所帮助,能够解决字符串解码问题。

如果你喜欢本文,也请务必点赞、收藏、评论、转发,这会对我有非常大的帮助。请我喝杯冰可乐也是极好的!

已完结,欢迎持续关注。下次见~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1161255.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VSCode 设置平滑光标

1.点击左下角的设置按钮&#xff0c;再点击设置 2.点击文本编辑器&#xff0c;点击光标&#xff0c;勾选控制是否启用平滑插入动画。 3.随便打开一个文件&#xff0c;上下左右移动光标时&#xff0c;会发现非常的流畅。 原创作者&#xff1a;吴小糖 创作时间&#xff1a;2023…

【AUTOSAR】【以太网】EthSyn

AUTOSAR专栏——总目录_嵌入式知行合一的博客-CSDN博客文章浏览阅读215次。本文主要汇总该专栏文章,以方便各位读者阅读。https://xianfan.blog.csdn.net/article/details/132072415 目录 一、概述 二、功能描述 2.1 初始化

深入了解进口跨境商城源码的电商开发的关键

随着全球电子商务的快速发展&#xff0c;进口跨境商城源码的电商开发逐渐成为一种趋势。本文将深入探讨进口跨境商城源码的电商开发的关键&#xff0c;包括需求分析、技术实现、运营推广、风险控制等方面。 一、需求分析 在进口跨境商城源码的电商开发中&#xff0c;需求分析是…

【C/C++】 常量指针、指针常量、指向常量的常指针

const修饰指针的三种情况 int main() {int a 10;int b 10;//常量指针//const修饰的是int&#xff0c;指针指向可以改&#xff0c;指针指向的值不可以更改const int * p1 &a; p1 &b; //正确//*p1 100; 报错//指针常量//const修饰的是指针&#xff0c;指针的值&am…

Appium 移动端自动化测试 —— 触摸(TouchAction) 与多点触控(MultiAction)

一、触摸 TouchAction 在所有的 Appium 客户端库里&#xff0c;TouchAction 触摸对象被创建并被赋予一连串的事件。 规范里可用的事件有&#xff1a; * 短按(press) * 释放(release) * 移动到(moveTo) * 点击(tap) * 等待(wait) * 长按(longPress) * 取消(cancel) * 执行(per…

Unity屏幕中涂鸦

LineRenderer LineRenderer是Unity中的一个组件&#xff0c;用于在场景中绘制简单的线段。 LineRenderer组件允许你通过设置一系列顶点来定义线段的形状和外观。它会根据这些顶点自动在场景中绘制出线段。 下面是LineRenderer的一些重要属性和方法&#xff1a; positionCou…

串口通信(6)应用定时器中断+串口中断实现接收一串数据

本文为博主 日月同辉&#xff0c;与我共生&#xff0c;csdn原创首发。希望看完后能对你有所帮助&#xff0c;不足之处请指正&#xff01;一起交流学习&#xff0c;共同进步&#xff01; > 发布人&#xff1a;日月同辉,与我共生_单片机-CSDN博客 > 欢迎你为独创博主日月同…

LICEcap使用教程

打开LICEcap&#xff0c;显示如下 点击Record&#xff0c;开始录制 点击Stop&#xff0c;停止录制 点击Record&#xff0c;进入该页面 display in animation&#xff08;在动画中显示&#xff09; title frame&#xff08;标题框&#xff09; - - - sec&#xff08;秒&…

网络安全应急响应工具(系统痕迹采集)-FireKylin

文章目录 网络安全应急响应工具(系统痕迹采集)-FireKylin1.FireKylin介绍【v1.4.0】 2021-12-20【v1.0.1】 2021-08-09 2.客户端界面Agent支持的操作系统FireKylinAgent界面使用方式比较传统方式与FireKylin比较无法可达目标的场景应用对比 3.使用教程设置语言Agent配置&#x…

Vue路由导航(replace、push、forward、back、go)

Vue路由导航&#xff08;replace、push、forward、back、go&#xff09; 先了解栈结构&#xff0c;再学习以下内容 栈的数据结构&#xff1a;先进后出&#xff0c;后进先出。原理&#xff1a;push将元素压入栈内&#xff0c;pop将元素弹出&#xff0c;栈有分别有栈底指针和栈顶…

Linux系统编程,socket通信编程实践练习(C语言)

文章目录 Linux系统编程&#xff0c;socket通信编程实践练习&#xff08;C语言&#xff09;1.服务端代码2.客户端代码 Linux系统编程&#xff0c;socket通信编程实践练习&#xff08;C语言&#xff09; 1.服务端代码 #include <stdio.h> #include <stdlib.h> #in…

Linux纯C串口开发

为什么要用纯C语言 为了数据流动加速&#xff0c;实现低配CPU建立高速数据流而不用CPU干预&#xff0c;避免串口数据流多次反复上升到软件应用层又下降低到硬件协议层。 关于termios.h 麻烦的是&#xff0c;在 Linux 中使用串口并不是一件最简单的事情。在处理 termios.h 标头…

Geth的进行合约部署和调用合约方法

环境 Ubuntu20 geth : 1.10.5-stable go: 1.17 前言 还未安装geth的读者可以参考这篇文章 Geth的安装并简单使用篇 我们需要进入geth交互式控制台进行操作 root192-168-19-133:~# geth --dev console INFO [10-03|22:25:29.918] Starting Geth in ephemeral dev mode... INFO…

list集合中的元素排序

目录 一、利用lambda对list集合排序 二、对对象集合操作&#xff0c;其实与基本类型集合操作类似 三、对 JSONArray 排序 一、利用lambda对list集合排序 先定义一个集合 List<Integer> list new ArrayList<>(); list.add(1); list.add(5); list.add(4); list…

基于SSM的酒店客房预定管理系统

基于SSM的酒店客房预定管理系统的设计与实现~ 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringSpringMVCMyBatis工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 前台主页 客房详情 登录界面 管理员界面 用户界面 摘要 基于SSM&#xff08;…

逻辑分析仪与示波器选择

一、简介 逻辑分析仪是利用时钟从测试设备上采集和显示数字信号的仪器&#xff0c;最主要的作用在于时序判定。逻辑分析仪与示波器不同&#xff0c;它不能显示连续的模拟量波形&#xff0c;而只显示高低两种电平状态&#xff08;逻辑1和0&#xff09;。在设置了参考电压后&…

JDK环境变量配置

windows系统 1. win建 r 输入sysdm.cpl打开系统属性界面。选择高级栏目&#xff0c;点击环境变量菜单。 2. 选择系统变量中的新建&#xff0c;变量名输入JAVA_HOME&#xff0c;变量值输入jdk安装目录&#xff0c;例如&#xff1a;D:\Java\jdk1.8.0_91。 3. 选择编辑系统变量中…

容斥原理,多步容斥

容斥意义法 设计状态表示容斥的过程。比较简单的容斥题目一般可以容斥意义。 如果我们要求方案数的话&#xff0c;通常情况下我们的把限制视为两个方面&#xff0c;一方面是总限制&#xff0c;一方面是对于每个物品的限制&#xff0c;这样设集合 S i S_i Si​表示满足总限制以及…

VSCode 如何设置背景图片

VSCode 设置背景图片 1.打开应用商店&#xff0c;搜索 background &#xff0c;选择第一个&#xff0c;点击安装。 2. 安装完成后点击设置&#xff0c;点击扩展设置。 3.点击在 settings.json 中编辑。 4.将原代码注释后&#xff0c;加入以下代码。 // { // "workben…

中海达守护电力人员作业安全

近日&#xff0c;中海达为电网某换流站作业人员提供的160余套北斗高精度定位产品顺利完成交付。通过使用北斗高精度定位技术&#xff0c;帮助换流站实现了人员&#xff08;车辆&#xff09;位置实时定位、电子围栏实时预警、远程作业指导等应用效果&#xff0c;用高科技保障电网…