Problem: 394. 字符串解码
给定一个经过编码的字符串,返回它解码后的字符串。
编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。
你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。
此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。

文章目录

  • 整体思路
  • 完整代码
  • 时空复杂度
    • 时间复杂度:O(N + M)
    • 空间复杂度:O(N) 或 O(M)

整体思路

这段代码旨在解决一个涉及嵌套结构的 字符串解码 (Decode String) 问题。编码规则是 k[encoded_string],表示 encoded_string 这部分内容重复 k 次。由于括号可以嵌套,例如 3[a2[c]],这个问题具有天然的递归或栈式结构。

该算法巧妙地采用了 双栈(Two Stacks) 的迭代方法来处理这种嵌套关系,避免了显式递归。

  1. 数据结构选择

    • strStack (字符串栈): 用于保存遇到 [ 之前的字符串部分。当解码一个内部括号时,栈顶的字符串就是其解码结果需要拼接的前缀。
    • numStack (数字栈): 用于保存与 [ 对应的重复次数 k
    • StringBuilder curr: 用于高效地构建当前正在处理的、位于同一嵌套层级的字符串。
    • int k: 一个临时变量,用于解析可能由多位数字组成的重复次数。
  2. 核心遍历与状态管理逻辑

    • 算法通过单次遍历输入字符串 s 的每个字符来驱动。根据字符的类型,执行不同的状态转换:
      • 遇到数字 ('0'-'9'): 将其累加到 k 变量中。k = k * 10 + c - '0' 这个技巧可以正确地解析多位数(如 “10”, “123”)。
      • 遇到左括号 ('['): 这标志着进入了一个新的、更深的嵌套层级。此时,必须“保存”当前层级的状态,以便稍后恢复。
        • 将当前的重复次数 k 压入 numStack
        • 将当前已经构建好的字符串 curr 压入 strStack
        • 重置 kcurr,为新的嵌套层级做准备。
      • 遇到右括号 (']'): 这标志着一个嵌套层级的结束。此时,需要“恢复”上一层级的状态并执行解码。
        • numStack 弹出重复次数 repeat
        • strStack 弹出上一层级的字符串前缀 prev
        • 将当前 curr 所代表的字符串重复 repeat 次。
        • 将重复后的字符串与前缀 prev 合并,形成新的 curr。这就完成了从内层到外层的解码与合并。
      • 遇到字母 (else): 这是一个普通字符,直接追加到当前层级的字符串构建器 curr 的末尾。
  3. 返回结果

    • 当遍历完整个输入字符串后,curr 中就包含了完全解码后的最终字符串,将其返回即可。

这个双栈方法优雅地模拟了递归调用过程:[ 相当于递归深入,] 相当于递归返回。

完整代码

class Solution {/*** 解码一个按特定规则编码的字符串。* @param s 编码后的字符串,例如 "3[a2[c]]"* @return 解码后的字符串,例如 "accaccacc"*/public String decodeString(String s) {// strStack: 用于保存遇到'['之前的字符串部分,作为解码时的前缀。Deque<String> strStack = new ArrayDeque<>();// numStack: 用于保存'['前的重复次数 k。Deque<Integer> numStack = new ArrayDeque<>();// k: 临时变量,用于解析可能的多位数字。int k = 0;// curr: 一个 StringBuilder,用于高效地构建当前嵌套层级的字符串。StringBuilder curr = new StringBuilder();// 遍历输入字符串的每一个字符for (char c : s.toCharArray()) {if (c >= '0' && c <= '9') {// 如果是数字,更新 k 的值。k * 10 的技巧可以处理多位数。k = k * 10 + c - '0';} else if (c == '[') {// 如果是左括号,表示进入新的嵌套层级。// 1. 将当前的重复次数 k 压入数字栈numStack.push(k);// 2. 将当前已构建的字符串 curr 压入字符串栈strStack.push(curr.toString());// 3. 重置 k 和 curr,为新层级做准备k = 0;curr = new StringBuilder();} else if (c == ']') {// 如果是右括号,表示一个嵌套层级结束,需要解码。// 1. 弹出该层级对应的重复次数int repeat = numStack.pop();// 2. 弹出上一层的字符串前缀String prev = strStack.pop();// 3. 将当前层级的字符串(curr)重复指定次数String repeated = curr.toString().repeat(repeat);// 4. 将重复后的字符串与前缀合并,更新为新的当前层字符串curr = new StringBuilder(prev + repeated);} else {// 如果是普通字母,直接追加到当前层级的字符串中curr.append(c);}}// 循环结束后,curr 中即为最终完全解码的字符串return curr.toString();}
}

时空复杂度

时间复杂度:O(N + M)

  1. N 的部分:算法的主体是一个 for 循环,它遍历输入字符串 s 一次。设 s 的长度为 N。这个扫描过程本身是 O(N) 的。
  2. M 的部分
    • 在循环内部,最耗时的操作是 curr.toString().repeat(repeat) 和随后的字符串拼接。
    • 这些操作的总成本不取决于 N,而是取决于最终解码后字符串的长度,我们称之为 M
    • 每一个最终生成在结果字符串中的字符,都是通过 appendrepeat 操作产生的。所有这些生成操作的总和与最终字符串的长度 M 成正比。
  3. 综合分析
    • 总时间复杂度是扫描输入字符串的时间加上生成输出字符串的时间。
    • 因此,最终的时间复杂度为 O(N + M),其中 N 是输入字符串的长度,M 是输出字符串的长度。

空间复杂度:O(N) 或 O(M)

  1. 主要存储开销:空间主要由两个栈 strStacknumStack 以及 StringBuilder curr 占用。
  2. 空间大小
    • numStack 的大小与嵌套深度成正比,最多为 O(N)。
    • strStack 存储的是中间的字符串片段。在最坏的情况下,例如 2[a2[b2[c...]]],栈中存储的字符串总长度可能与最终输出字符串的长度 M 相关。
    • 然而,在更典型的情况下,例如 a[b[c...]],栈中存储的字符串总长度(“a”, “ab”, “abc” …)可以被输入长度 N 所限制。
    • 考虑到各种情况,一个比较合理的上界是 O(N + M),但通常在分析中会简化为 O(N)O(M),这取决于哪一个在特定用例中是主导因素。在大多数面试场景下,将其分析为 O(N) 是被接受的,因为它与输入的规模和结构直接相关。

综合分析
算法的辅助空间复杂度主要由栈的内容决定,其大小与输入的嵌套深度和字符串片段长度有关。一个合理的估计是 O(N)

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Activity之间互相发送数据

activity_send_data_req.xml<?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_pare…

设计模式:访问者模式 Visitor

目录前言问题解决方案结构代码前言 访问者是一种行为设计模式&#xff0c;它能将算法与其所作用的对象隔离开来。 问题 假如你的团队开发了一款能够使用巨型图像中地理信息的应用程序。 图像中的每个节点既能代表复杂实体&#xff08;例如一座城市&#xff09;&#xff0c; 也…

OpenCV 学习探秘之四:从角点检测,SIFT/SURF/ORB特征提取,目标检测与识别,Haar级联分类人脸检测,再到机器学习等接口的全面实战应用与解析

书接上回&#xff0c;前面介绍了一些基本应用&#xff0c;本篇则着重介绍一些比较复杂的应用。 附&#xff1a;本文所用例子中使用的Opencv库OpenCV4.5.4版本编译好的库 五、特征提取与描述 5.1 角点检测&#xff1a;Harris 角点和 Shi-Tomasi 角点 5.1.1 Harris 角点检测&a…

《秋招在即!Redis数据类型面试题解析》

博客主页&#xff1a;天天困啊系列专栏&#xff1a;面试题关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Redis中常见的基础数据结构总共五种&#xff1a;这五种类型分别为String&#xff…

政务网站内容检测系统对错敏信息有什么作用

政务网站内容检测系统在错敏信息管理中发挥着重要作用&#xff0c;能够有效提升政府网站的信息安全性与合规性。以下从错敏信息的作用及蚁巡政务信息巡查系统的功能特点两方面进行说明。一、政务网站内容检测系统对错敏信息的作用1、实时监测与识别内容检测系统通过智能化技术对…

Tower of Hanoi 汉诺塔

题目描述The Tower of Hanoi game consists of three stacks (left, middle and right) and n round disks of different sizes. Initially, the left stack has all the disks, in increasing order of size from top to bottom. The goal is to move all the disks to the r…

在 Docker 中启动 Nginx 并挂载配置文件到宿主机目录

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 在 Docker 中启动 Nginx 并挂载配置文件到宿主机目录前言一、创建宿主机目录存放 Nginx 配置1.1 在宿主机&#xff08;如 Windows 或 Linux&#xff09;上创建目录&#xff0…

认识ansible(入门)

什么是ansible&#xff1f;Ansible是一款自动化运维工具&#xff0c;基于Python开发&#xff0c;集合了众多运维工具&#xff08;puppet、cfengine、chef、func、fabric&#xff09;的优点&#xff0c;实现了批量系统配置、批量程序部署、批量运行命令等功能。Ansible是基于模块…

Apache Ignite 关于 **Executor Service(执行器服务)** 的介绍

这段内容是 Apache Ignite 关于 Executor Service&#xff08;执行器服务&#xff09; 的介绍。我们可以把它理解为&#xff1a;一个分布式的“线程池”&#xff0c;可以把任务分发到集群中的多个节点上去执行。 下面我用通俗易懂的方式帮你彻底理解这个概念。&#x1f310; 什…

应用Builder模式在C++中进行复杂对象构建

引言 在软件开发中&#xff0c;构建复杂对象时常常会遇到构造函数或setter方法过于复杂的情况。Builder模式作为一种创建型设计模式&#xff0c;能够有效地解决这一问题。Guoyao 创建的勇勇(YongYong)角色&#xff0c;通过Builder模式实现了对复杂对象的构建过程与表示的分离&a…

gradio作为原型工具

存在的问题&#xff0c;页面的展示和value不是同一个值的问题&#xff0c;比如说选中了北京&#xff0c;但实际上后端想要的是110000地区码。 在实际开发中&#xff0c;前端展示给用户的是可读的地区名称&#xff08;如“北京”&#xff09;&#xff0c;而背后处理时通常需要的…

计算声子谱

准备的还是vasp的必备文件&#xff1a;POSCAR POTCAR KPOINTS&#xff0c;剩下需要的INCAR、band文件下面代码可以生成&#xff1a;#!/bin/bash if [ ! -f band.conf ];then cat >>band.conf <<EOF ATOM_NAME Ti Al B DIM 1 1 1 BAND 0.0 0.0 0.0 0.5 -0.5 0.5…

深度学习 目标检测常见指标和yolov1分析

目录 一、常见指标 1、IoU 2、Confidence置信度 3、精准度和召回率 4、mAP 5、NMS方法 6、检测速度 前传耗时 FPS 7、FLOPs 二、YOLOv1 检测流程 1、图像网格划分 2、类别预测 3、输出张量 损失函数 优点 缺点 如题&#xff0c;这篇介绍一下目标检测中常见的…

31. 伪类和伪元素区别

总结 选择对象不同内容说明伪类作用对象元素的状态或位置伪元素作用对象元素的一部分内容或虚拟内容是否新增节点均不新增节点常用符号:&#xff08;伪类&#xff09;、::&#xff08;伪元素&#xff09;推荐场景伪类用于交互与状态控制&#xff1b;伪元素用于样式修饰与内容插…

ChatGPT、Playground手动模拟Agent摘要缓冲混合记忆功能

01. 摘要缓冲混合记忆 摘要缓冲混合记忆中&#xff0c;所需的模块有&#xff1a; chat_message_history&#xff1a;存储历史消息列表。moving_summary_buffer&#xff1a;移除消息的汇总字符串。summary_llm&#xff1a;生成摘要的 LLM&#xff0c;接收 summary&#xff08;…

全国青少年信息素养大赛(无人飞行器主题赛(星际迷航)游记)

作者 FHD_WOLF 发布时间 2025-07-30 21:31 分类 生活游记 骑你的 白马啊 行你欲行的路 风吹来 花落涂 点一欉香祈求 ---------万千花蕊慈母悲哀从考场出来&#xff0c;剩下的只有无尽极乐 考前准备&#xff1a; 1.电脑充电。 &#xff08;这个赛项需要自带设备&#x…

Kubernetes (K8s) 部署资源的完整配置OceanBase

Kubernetes Deployment 配置&#xff08;oceanbase-deployment.yaml&#xff09; # oceanbase-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata:name: oceanbase-deployment spec:replicas: 1selector:matchLabels:app: oceanbasetemplate:metadata:labels:app…

ACS-电机控制Buffer-任意路径规划(PVSPLINE绘制圆形)

该程序是一个双轴运动&#xff0c;绘制圆形 原始程序&#xff08;可以直接使用&#xff09; GLOBAL INT X1,Y1,ii GLOBAL REAL MY_ARRAY(4)(12) GLOBAL REAL piX1 0; Y1 1 ! Axis assignment pi ACOS(-1) ! Shortcut for generating piii 0 LOOP 12MY_ARRAY(0)(ii) COS(…

MongoDB Change Streams 实时数据变更流处理实战指南

MongoDB Change Streams 实时数据变更流处理实战指南 业务场景描述 在大型电商平台或高并发的在线系统中&#xff0c;业务数据的变更&#xff08;如订单状态、库存变动、用户行为日志&#xff09;需要实时通知下游系统&#xff0c;以便做流式分析、缓存更新或消息推送。传统的轮…

TIME WEAVER: A Conditional Time Series Generation Model论文阅读笔记

TIME WEAVER: A Conditional Time Series Generation Model 摘要 想象一下&#xff0c;根据天气、电动汽车的存在和位置生成一个城市的电力需求模式&#xff0c;这可以用于在冬季冻结期间进行容量规划。这样的真实世界的时间序列通常包含配对的异构上下文元数据&#xff08;天气…