利用flag信号解决LeetCode题库第394题字符串解码问题

394. 字符串解码

中等

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

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

分析:

对于一个输入的原始字符串s,我的想法是:

1、先把这个字符串分解为基本的子字符串

基本的子字符串有以下几种形式:

(1)一是形如3[a],一个数字加上中括号中的字符或字符串

(2)一是形如3[ab2[c]3[bc]],除了有数字,中括号里面还嵌套的有数字和中括号,是一种复合形式,需要层层剥去中括号,直到不含中括号为止

(3)另一种是ef或xyz这种不含数字和中括号的纯字母字符串

2、然后对每一个子字符串分别进行解码处理

3、最后将解码之后的字符串按顺序拼合起来,即得到问题的结果。

下表可以看出这种处理的过程

函数mdecode(s)可以对分解之后的子字符串进行解码处理

那么如何将一个原始字符串s分解为符合条件的子字符串呢?

为了使分割的方法更具有通用性,我们使用了一个列表a来记录分割的位置,首先把字符串s的0索引位置加入在a中,然后找到第一个数字的位置,并把这个位置索引加入a,如果0索引位置就是数字的话,则有重复的位置号,后面再去重即可解决。当找到“]”之后,将从之前找到的数字位置到这个“]”位置进行切片,注意要包含这个“]”字符,并判断切出的字符串中“[”“]”的个数是否相等,如果相等则将“]”的索引加入a列表。按照这个的方法重复操作直到s的结尾,最后再把结束索引加入列表a。

对a去重,通过a中给定的索引号位置,对s进行切片处理即可分割为一些基本的子字符串,并存储于列表b中

程序如下:

#函数mdecode(s),对形如‘abc'或3[bc]之类的字符串进行解码
def mdecode(s):
    if '[' not in s and ']' not in s:
        return s
    else:
        i=s.index('[')
        n=s[:i]
        ms=s[i+1:len(s)-1]
        return ms*int(n)

def cl(s):
    n=len(s)
    a=[0]
    flag=False #flag为False,则开始取子字符串,为True则还未到字符串结束位置
    start=0    
    for i in range(n):
        if s[i] in '123456789' and not flag:
            a.append(i)
            start=i
            flag=True
        elif s[i]==']':
            x=s[start:i+1]
            if x.count('[')==x.count(']'):
                a.append(i+1)
                flag=False
    a.append(n)

    #a去重
    b=list(set(a))
    for i in b:
        if a.count(i)>1:
            a.remove(i)
    print('子字符串起始和结束位置索引号:',a)
    b=[]
    for i in range(len(a)-1):
        x=s[a[i]:a[i+1]]
        b.append(x)
    print('子字符串列表:',b)

    a=''
    for i in b:
        a+=mdecode(i)
    return a
#输入字符串s
s=input('pls input s=')
while True:
    a=cl(s)
    if a.count('[')==0:
        break
    else:
        s=cl(a)
        
print('解码之后的字符串:',a)

运行实例1

pls input s=abc3[a]2[d]xy
子字符串起始和结束位置索引号: [0, 3, 7, 11, 13]
子字符串列表: ['abc', '3[a]', '2[d]', 'xy']
解码之后的字符串: abcaaaddxy
 

运行实例2

pls input s=3[a2[bc]3[b]]
子字符串起始和结束位置索引号: [0, 13]
子字符串列表: ['3[a2[bc]3[b]]']
子字符串起始和结束位置索引号: [0, 1, 6, 10, 11, 16, 20, 21, 26, 30]
子字符串列表: ['a', '2[bc]', '3[b]', 'a', '2[bc]', '3[b]', 'a', '2[bc]', '3[b]']
子字符串起始和结束位置索引号: [0, 24]
子字符串列表: ['abcbcbbbabcbcbbbabcbcbbb']
解码之后的字符串: abcbcbbbabcbcbbbabcbcbbb

运行实例3

pls input s=3[ab2[c]3[bc]ac]
子字符串起始和结束位置索引号: [0, 16]
子字符串列表: ['3[ab2[c]3[bc]ac]']
子字符串起始和结束位置索引号: [0, 2, 6, 11, 15, 19, 24, 28, 32, 37, 39]
子字符串列表: ['ab', '2[c]', '3[bc]', 'acab', '2[c]', '3[bc]', 'acab', '2[c]', '3[bc]', 'ac']
子字符串起始和结束位置索引号: [0, 36]
子字符串列表: ['abccbcbcbcacabccbcbcbcacabccbcbcbcac']
解码之后的字符串: abccbcbcbcacabccbcbcbcacabccbcbcbcac

运行实例4

pls input s=efg

子字符串起始和结束位置索引号: [0, 3]

子字符串列表: ['efg']

解码之后的字符串: efg

运行实例5

pls input s=3[2[ab2[b]2[c]]]
子字符串起始和结束位置索引号: [0, 16]
子字符串列表: ['3[2[ab2[b]2[c]]]']
子字符串起始和结束位置索引号: [0, 13, 26, 39]
子字符串列表: ['2[ab2[b]2[c]]', '2[ab2[b]2[c]]', '2[ab2[b]2[c]]']
子字符串起始和结束位置索引号: [0, 2, 6, 10, 12, 16, 20, 22, 26, 30, 32, 36, 40, 42, 46, 50, 52, 56, 60]
子字符串列表: ['ab', '2[b]', '2[c]', 'ab', '2[b]', '2[c]', 'ab', '2[b]', '2[c]', 'ab', '2[b]', '2[c]', 'ab', '2[b]', '2[c]', 'ab', '2[b]', '2[c]']
解码之后的字符串: abbbccabbbccabbbccabbbccabbbccabbbcc

感悟:

在解决问题的过程中,刚开始程序只能处理简单的情况,也就是只有一层中括号的情况,对于那种有中括号嵌套的复合字符串还是无法处理,让我好一阵失望,这才让我去思考更为通用的解码方法。

问题是慢慢解决的,不可能一口吃一个胖子。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值