某大厂的机试题,解压压缩的字母串

简介: 这几天看到一个大厂的面试题,感觉比较有意思,是学习递归的好题目,下面和大家分享一下这道题的解法。

 这几天看到一个大厂的面试题,感觉比较有意思,是学习递归的好题目,下面和大家分享一下这道题的解法。

题目说明:

压缩的字母规则是,连续相同的字母串压缩成:连续的个数 +[字母串]。如 aaa,压缩成:3[a];amamam 压缩成 3[am]。

请实现解压缩字符串功能。实现程序语言不限制。完成时间两个小时,过程不能看手机,不能切屏。

自测样例,输入:3[k] 2[am] 预期输出:kkkamam

输入:2[k3[am]] 预期输出:kamamamkamamam

解题思路:

这个题目初看,解压缩的算法不难设计,只需要进行简单的递归就可以了,这里就不再赘述,而不用递归而且保证算法在o(n)时间内完成倒是有些难度。

这里需要用到栈的思想处理,倒序完成。

1.初始态中将输入字符串赋值给结果

2.找到最后一个[符号,取出其前面的数字以及与这个[最近的]符号,之间的所有字符,将这些字符串按照数字的个数展开,并用展开后的字符串对于数字[字符串]的原结构进行替换,保存到结果当中。

3处理完所有[即可完成解压。

代码如下:

import re
def UnFoldString(repeat,strInput):
    if repeat<1:
        return None
    result=""
    for i in range(0,repeat):
        result=result+strInput
    return result
def UnCompressString(strInput):
    pat = r'\d+'
    result=strInput
    numlist = re.findall(pat, strInput)#把所有数字通过re匹配出来,这个做法只适用于Python,后续可以优化
    numIndex= len(numlist)-1#记录目前展开的位置
    for j in range(0,len(result)):#遍历一次复杂度o(n)
        i= len(result)-1-j#关键在于使用栈的方式,从后找到最后一个[
        if result[i]=='[':
            numlen=len(numlist[numIndex])
            #print(numlen,i,numlist[numIndex],result[i-numlen:i])
            if result[i-numlen:i]!=numlist[numIndex]:#如果最后一个[前面不是最后一个数字,肯定是有问题的
                return None
            else:
                compressStr=result[i+1:].split(']')[0]#当前位置i对应的是[,那么从i+1到下一个]一定是要解压的字符,通过split方式最直观
                comressStrLen=len(compressStr)+2
                result=result[:i-numlen]+UnFoldString(int(numlist[numIndex]),compressStr)+result[i+comressStrLen:]
                numIndex=numIndex-1
    return result
strInput="3[k]2[am]"
print(UnCompressString(strInput))
strInput="2[k3[am]]"
print(UnCompressString(strInput))
strInput="12[k3[am]]"
print(UnCompressString(strInput))

image.gif

发散题目:

当然这题做到这肯定没结束,如果在面试中出现这道题目,我肯定会问对于压缩算法的实现策略,也就是把输入输出调转过来。

输入:kamamamkamamam 预期输出: 2[k3[am]]

这个想递归实现的方式都不简单。

可以先考虑下基本思路,因为这个结果需要嵌套,也就是左子串,右子串和中间你已经找到的最长子串都需要进行递归。

其中找最长的子串可以考虑贪心算法,直接按照字符串一半长度逐步尝试。

然后逐步向右移位。把左、右半边不在最长子串中的序列递归压缩。

具体代码及注释如下:

def FindMaxsubstring(strInput):
    #print(strInput)
    strlen=len(strInput)
    if strlen<2:
        return 0,strInput,strlen
    repeat=1
    subStr=""
    if strlen==2:
        if strInput[0]==strInput[1]:
            return 2,strInput[0],strlen
        else:
          return 0,strInput,strlen
    for i in range(0,int(strlen/2)):
        greedyIndex=int(strlen/2)-i
        if greedyIndex<1:
            break
        repeatMax=int(strlen/greedyIndex)
        j=2
        while strInput[:greedyIndex]==strInput[greedyIndex*(j-1):greedyIndex*j]:
            j=j+1
            repeat=repeat+1
            subStr=strInput[:greedyIndex]
            strlen=greedyIndex
        if repeat>1:
            return repeat,subStr,greedyIndex*repeat
    return 0, strInput, strlen
def GenResult(strInput):
    repeat,lastRepeat=0,0
    subStr,lastSubStr="",""
    lastLen=0
    leftIndex=0
    strLen=len(strInput)
    rightIndex=strLen
    if strLen<2:
        return strInput
    for i in range(0,strLen-1):
        lastRepeat,lastSubStr,lastRightIndex=FindMaxsubstring(strInput[i:])
        if lastRepeat>1 and len(lastSubStr)>lastLen:
            #print(lastSubStr,str(i))
            repeat=lastRepeat
            lastLen = len(lastSubStr)
            subStr=lastSubStr#递归生成子串
            rightIndex=lastRightIndex
            leftIndex=i
    if repeat <2:
        return strInput
    if leftIndex<2 and (strLen-rightIndex)<2:
        return strInput[:leftIndex]+str(repeat)+"["+GenResult(subStr)+"]"+strInput[rightIndex+leftIndex:]
    else:
        return GenResult(strInput[:leftIndex]) + str(repeat) + "[" + GenResult(subStr) + "]" + GenResult(strInput[rightIndex+leftIndex:])
print(GenResult("kkkamam"))
print(GenResult("kamamamkamamam"))

image.gif


相关文章
|
6月前
实现一个函数可以左旋字符串中的k个字符包学会!(两种办法)
实现一个函数可以左旋字符串中的k个字符包学会!(两种办法)
44 1
|
3天前
|
Unix Shell 开发者
掌握 `fnmatch` 与 `fnmatchcase`:从文件名到街道地址的全能字符串匹配技巧
本文介绍了 Python 中 `fnmatch` 和 `fnmatchcase` 函数的使用方法,包括它们的功能、参数、返回值及应用场景。`fnmatch` 对大小写不敏感,适合大多数文件名匹配需求;而 `fnmatchcase` 则区分大小写,适用于需要精确匹配的场合。文章通过具体示例展示了这两个函数在文件过滤、URL 匹配及非文件名式字符串匹配中的应用。
|
3月前
|
C++
串应用- 计算一个串的最长的真前后缀
这篇文章提供了一个C++程序,用于找出给定字符串的最长真前后缀,并展示了如何通过计算每个子串的最长相同前后缀来实现这一功能。
|
5月前
1078 字符串压缩与解压 (20 分)
1078 字符串压缩与解压 (20 分)
|
6月前
|
弹性计算 运维 Shell
【每日挠头算法题(2)】压缩字符串|仅执行一次字符串交换能否使两个字符串相等
【每日挠头算法题(2)】压缩字符串|仅执行一次字符串交换能否使两个字符串相等
|
6月前
|
算法 测试技术
【动态规划】【字符串】【行程码】1531. 压缩字符串
【动态规划】【字符串】【行程码】1531. 压缩字符串
PTA 1078 字符串压缩与解压 (20 分)
文本压缩有很多种方法,这里我们只考虑最简单的一种:把由相同字符组成的一个连续的片段用这个字符和片段中含有这个字符的个数来表示。
116 0