字符串解码问题

字符串,解码,问题 · 浏览次数 : 73

小编点评

**问题解析** 字符串解码问题是一个递归算法,用于在指定字符串中解码其编码后的形式。 **代码实现** ```java class Solution { public static String decodeString(String s) { char[] str = s.toCharArray(); int len = str.length; return p(str, len, 0)[0]; } private static String[] p(char[] str, int n, int from) { StringBuilder sb = new StringBuilder(); int pre = 0; int i = from; while (i != n && str[i] != ']') { if (Character.isLowerCase(str[i]) || Character.isUpperCase(str[i])) { sb.append(str[i++]); } else if (Character.isDigit(str[i])) { // 数字 pre = pre * 10 + Integer.parseInt(String.valueOf(str[i++])); } else if ('[' == str[i]) { // 左括号 String[] bra = p(str, n, i + 1); sb.append(build(pre, bra[0])); pre = 0; i = Integer.parseInt(bra[1]) + 1; } } return new String[] {sb.toString(), String.valueOf(i)}; } private static String build(int pre, String s) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < pre; i++) { sb.append(s); } return sb.toString(); } } ``` **算法思路** 该算法使用递归和字符串操作来逐步解码字符串。 * **初始化**: * `pre` 记录当前处理的数字或字母数量。 * `i` 记录当前匹配右括号的位置。 * **循环**: * 如果当前字符是字母,添加它到 `sb` 中。 * 如果当前字符是数字,将它添加到 `pre` 中并更新 `i`。 * 如果当前字符是左括号,递归调用 `p` 查找右括号的编码。 * 如果当前字符是 [,递归调用 `p` 查找匹配的右括号的编码。 * **结束**: * 如果 `i` 等于 `n`,说明已处理完字符串,返回 `sb.toString()`。 * 如果还有右括号,递归调用 `p` 继续处理。 **时间复杂度** 时间复杂度为 O(n),其中 n 是字符串的长度。这是因为每一步递归都只处理不超过 n 个字符的子字符串,并重复执行该操作 n 次。

正文

字符串解码问题

作者:Grey

原文地址:

博客园:字符串解码问题

CSDN:字符串解码问题

题目描述

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

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

题目链接见:LeetCode 394. Decode String

主要思路

定义递归函数

String[] p(char[] str, int n, int from)

递归含义表示,str 字符串从 from 开始一直到结尾或者右边括号生成的信息返回,返回值是一个长度为 2 的数组,例如

2[abc]3[cd]ef

这个字符串,递归函数在执行过程中,遇到第一个右括号的时候,就会结算出两个信息,

第一个信息:之前处理过的字符串是什么;

第二个信息:处理到了哪个位置。

所以,在经历第一次递归过程后,返回

String[] res

其中

res[0] = "abcabc"; // 第一次遇到],进行结算生成的字符串
res[1] = "5" // 处理到了第五个位置,即第一个]出现的位置

继续递归

res[0] = "abcabccdcdcd"; // 第二次遇到],进行结算生成的字符串,注:这里要拼接上上一次递归的"abcabc"
res[1] = "10" // 处理到了第十个位置,即第二个]出现的位置

继续,后续没有]了,所以一直到字符串最后,得到最终的结果

res[0] = "abcabccdcdcdef"; // 处理到了终止位置,结算之前拼接的字符串和最后遗留字符串拼接的最终结果
res[1] = "12"; // 处理到了终止位置

完整代码如下

class Solution {
  
  public static String decodeString(String s) {
    char[] str = s.toCharArray();
    int len = str.length;
    return p(str, len, 0)[0];
  }

  private static String[] p(char[] str, int n, int from) {
    StringBuilder sb = new StringBuilder();
    int pre = 0;
    int i = from;
    while (i != n && str[i] != ']') {
      if (Character.isLowerCase(str[i]) || Character.isUpperCase(str[i])) {
        // 字母
        sb.append(str[i++]);
      } else if (Character.isDigit(str[i])) {
        // 数字
        pre = pre * 10 + Integer.parseInt(String.valueOf(str[i++]));
      } else if ('[' == str[i]) {
        // 左括号
        String[] bra = p(str, n, i + 1);
        sb.append(build(pre, bra[0]));
        pre = 0;
        i = Integer.parseInt(bra[1]) + 1;
      }
    }
    return new String[] {sb.toString(), String.valueOf(i)};
  }

  private static String build(int pre, String s) {
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < pre; i++) {
      sb.append(s);
    }
    return sb.toString();
  }

}

代码说明

主要看p函数的while循环部分,其中i != n && str[i] != ']'就是控制每次递归只处理除了结尾位置和]位置的其他位置,遇到结尾或者]直接返回一次结算结果。

while中的三个分支也比较直白,对于字母的话,直接append就可以,对于数字,要处理一个简单的边界条件,即数字不一定是单个整数,可能是多位数,比如334[abc],对于[,就可以结算这个[匹配的右括号之间的内容:

        // 得到与其匹配的右括号之间的内容
        String[] bra = p(str, n, i + 1);
        sb.append(build(pre, bra[0]));
        pre = 0;
        // 去下一个位置匹配
        i = Integer.parseInt(bra[1]) + 1;

更多

算法和数据结构笔记

与字符串解码问题相似的内容:

字符串解码问题

字符串解码问题 作者:Grey 原文地址: 博客园:字符串解码问题 CSDN:字符串解码问题 题目描述 给定一个经过编码的字符串,返回它解码后的字符串。 编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。

go高并发之路——go语言如何解决并发问题

一、选择GO的原因 作为一个后端开发,日常工作中接触最多的两门语言就是PHP和GO了。无可否认,PHP确实是最好的语言(手动狗头哈哈),写起来真的很舒爽,没有任何心智负担,字符串和整型压根就不用区分,开发速度真的是比GO快很多。现在工作中也还是有一些老项目在使用PHP,但21年之后的新项目基本上就都

记录 Ucharts 的使用

1.开启 2d 渲染 线上运行开启 canvas2d 可以解决图表显示问题 canvasId 可以不传,官方内置生成随机字符串id的方法 注: 开启 2d 后,不能真机调试,只能开发者工具调试或扫二维码"预览"。 开启 2d 后,模拟

抖音验证签名和接口含中文签名,需要在发送端加上utf8编码

抖音验证签名和接口含中文签名,需要在发送端加上utf8编码 抖音验签和抖音异步通知回调验签解决:是对整个接收的字符串做验签,而不是部分数据做验签解决中文参数问题,否则中文乱码报验签错误 签名算法https://developer.open-douyin.com/docs/resource/zh-CN

算法基础(一):串匹配问题(BF,KMP算法)

好家伙,学算法, 这篇看完,如果没有学会KMP算法,麻烦给我点踩 希望你能拿起纸和笔,一边阅读一边思考,看完这篇文章大概需要(20分钟的时间) 我们学这个算法是为了解决串匹配的问题 那什么是串匹配? 举个例子: 我要在"彭于晏吴彦祖"这段字符串中找到"吴彦祖"字符串 这就是串匹配 这两个算法太抽象了

UnrecognizedPropertyException: Unrecognized field 解决

转载请注明出处: 在项目得不同环境上对接外部的服务接口,且存在不同版本间可能有字段不同得问题,遇到这种问题在使用jackson解析时,如果格式化得字符串与定义得java类不能完全对应时,就会报错:Unrecognized field ,代码还原: import com.fasterxml.jacks

C#移除字符串中的不可见Unicode字符

背景 最近发现某个数据采集的系统拿下来的数据,有些字段的JSON被莫名截断了,导致后续数据分析的时候解析JSON失败。 类似这样 {"title": "你好 或者这样,多了个双引号啥的 {"title":""你好"} 因为数据库是Oracle,起初以为是Oracle这老古董出问题了,结果一番折腾,把

C#11之原始字符串

最近.NET7.0和C#11相继发布,笔者也是第一时间就用上了C#11,其中C#11的有一个更新能解决困扰我多年的问题,也就是文章的标题原始字符串。 在使用C#11的原始字符串时,发现的一些有意思的东西,超出了我原本对它的期待,话不多说,我们一起来看看。 多年的困扰 我不知道大家有没有写过这样的代码

SDL3 入门(2):第一个窗口

在上一篇文章中我们已经利用 SDL 的日志接口实现了简单的字符串输出,实际上是解决了开发环境搭建问题,接下来我们将在已有代码的基础上继续开发,实现第一个窗口的创建和背景色绘制。 初始化 首先设置日志输出级别: SDL_SetLogPriorities(SDL_LOG_PRIORITY_VERBOSE

特斯拉产品研发创新中心 3 月 22 日笔试答案

本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 提问。 大家好,我是小彭。 昨天是 「特斯拉 2023 春季公开笔试 - 产品研发创新中心专场」,你参加了吗?这场笔试整体来看没有难到特别离谱的题,但需要一些思维。 竞赛题解一览 T1 · 亲密字符串(Easy) 题