【限时免费】20天拿下华为OD笔试之【栈】2023Q1A-解压缩算法【欧弟算法】全网注释最详细分类最全的华为OD真题题解

【栈】2023Q1A-解压缩算法

题目描述与示例

题目描述

现需要实现一种算法,能将一组压缩字符串还原成原始字符串,还原规则如下:

  1. 字符后面加数字 N,表示重复字符 N 次。例如:压缩内容为 A3,表示原始字符串为 AAA
  2. 花括号中的字符串加数字 N,表示花括号中的字符串重复 N 次。例如:压缩内容为{AB}3,表示原始字符串为 ABABAB
  3. 字符加 N 和花括号后面加 N,支持任意的嵌套,包括互相嵌套。例如:压缩内容可以{A3B1{C}3}3

输入描述

输入一行压缩后的字符串

输出描述

输出压缩前的字符串

说明

输入输出的字符串区分大小写。

输入的字符串长度的范围为[1, 10000],输出的字符串长度的范围为[1, 100000],数字 N 范围[1, 10000]

示例一

输入

A3

输出

AAA

说明

A3 代表 A 字符重复 3

示例二

输入

{A3B1{C}3}3

输出

AAABCCCAAABCCCAAABCCC

说明

{A3B1{C}3}3 代表 A 字符重复 3 次,B 字符重复 1 次,花括号中的 C 字符重复 3 次,最外层花括号中的 AAABCCC 重复 3

解题思路

注意,本题和LC394. 字符串解码非常类似。区别在于,本题用花括号表示嵌套而不是中括号,数字出现在花括号之后而不是之前。由于数字出现在括号后,属于一种后缀表达式,而后缀表达式是更加适合栈的计算的,因此本题更加简单。

这题也属于括号配对表达式求值综合起来的栈题。我们从前往后一次遍历原始字符串s中的字符ch,存在以下几种情况:

  1. 遇到字母,入栈
  2. 遇到左括号"{",入栈
  3. 遇到右括号"}",说明在此之前肯定存在一个左括号已经入栈,我们需要考虑这对括号之间的所有字符串,并且把这些字符串都合并在一起。所以我们要反复地弹出栈顶元素并记录在一个新的字符串str_in_bracket中,直到遇到左括号"{"
  4. 遇到数字,说明数字之前的字符串需要被重复,需要记录这个数字。

对于前两种入栈的情况,我们可以合并代码,即

if ch == "{" or ch.isalpha():
    stack.append(ch)

对于遇到右括号"}"的情况,代码如下:

if ch == "}":
    str_in_bracket = str()
    while(stack[-1] != "{"):
        str_in_bracket = stack.pop() + str_in_bracket
    stack.pop()    # 此时栈顶元素是"{",直接弹出
    stack.append(str_in_bracket)

对于遇到数字的情况,有两个地方需要考虑:

  1. 数字num的位数超过1位,如何储存数字。以下代码能够储存位数超过1的数字。
num = num * 10 + int(ch)
  1. 数字什么时候要使用。当一个数字num已经被完全储存,则应该使栈顶的字符串stack[-1]重复num次。这里的判断逻辑是,ch的下一位已经不是数字,或者ch已经到达s的尾部,说明数字已经储存完毕。
if i == len(s)-1 or not s[i+1].isdigit():
    stack[-1] *= num
    num = 0

另外要注意,数字num使用完毕之后,需要重置为0

上述代码整理后得到:

if ch.isdigit():
    num = num * 10 + int(ch)
    if i == len(s)-1 or not s[i+1].isdigit():
        stack[-1] *= num
        num = 0

时空复杂度

时间复杂度:O(N)。仅需一次遍历数组,每一个字符最多出入栈各一次。

空间复杂度:O(N)。栈所占用的额外空间。

代码

# 题目:2023Q1A-解压缩算法
# 分值:200
# 作者:闭着眼睛学数理化
# 算法:栈
# 代码看不懂的地方,请直接在群上提问

s = input()
stack = list()  # 初始化一个栈,在python中可以用list代替栈
num = 0         # 初始化一个变量num为0,用于栈中数字的记录

# 遍历整个字符串s
for i, ch in enumerate(s):
    # 遇到数字,进行数字的计算
    if ch.isdigit():
        # num乘10后加上int(ch)
        num = num * 10 + int(ch)
        # 如果i是s的最后一位索引,或者i的下一个位置i+1不是数字
        if i == len(s)-1 or not s[i+1].isdigit():
            # 那么需要令栈顶字符串重复num次
            stack[-1] *= num
            # 由于num已经使用完毕,需要重置num为0
            num = 0
    # 遇到左括号"{"或者字母,入栈
    elif ch == "{" or ch.isalpha():
        stack.append(ch)
    # 遇到右括号"}",说明前面必然存在一个左括号与其闭合
    # 将栈顶元素不断弹出,弹出的内容构建成一个新的字符串str_in_bracket
    # 直到遇到与其闭合的左括号,将str_in_bracket重新加入栈顶
    elif ch == "}":
        # 初始化该对闭合括号内的字符串str_in_bracket
        str_in_bracket = str()
        # 不断弹出栈顶元素,直到栈顶元素为一个左括号"{"
        while(stack[-1] != "{"):
            # 将弹出的元素加在str_in_bracket的前面
            str_in_bracket = stack.pop() + str_in_bracket
        # 把左括号弹出
        stack.pop()
        # 把str_in_bracket重新加入栈顶
        stack.append(str_in_bracket)

# 最后需要将栈中的所有字符串再用join()方法合并在一起并输出
print("".join(stack))

华为OD算法冲刺训练

  • 华为OD算法冲刺训练目前开始常态化报名!目前已服务100+同学成功上岸!

  • 课程讲师为全网50w+粉丝编程博主@吴师兄学算法 以及小红书头部编程博主@闭着眼睛学数理化

  • 每期人数维持在20人内,保证能够最大限度地满足到每一个同学的需求,达到和1v1同样的学习效果!

  • 30+天陪伴式学习,20+直播课时,300+动画图解视频,200+LeetCode经典题,100+华为OD真题,还有简历修改与模拟面试将为你解锁

  • 可查看链接 OD算法冲刺训练课程表 & OD真题汇总(持续更新)

  • 绿色聊天软件戳 od1336了解更多

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值