python实现:回文字符串问题(快手2019年秋季校园招聘编程题算法B试卷(牛客网))

目录

问题

解题思路

python具体实现

题外话


[编程题] 回文字符串

时间限制:1秒

空间限制:32768K

问题

最大回文子串是被研究得比较多的一个经典问题。最近月神想到了一个变种,对于一个字符串,如果不要求子串连续,那么一个字符串的最大回文子串的最大长度是多少呢。


输入描述:

每个测试用例输入一行字符串(由数字0-9,字母a-z、A-Z构成),字条串长度大于0且不大于1000.

输出描述:

输出该字符串的最长回文子串的长度。(不要求输出最长回文串,并且子串不要求连续)

输入例子1:

adbca

输出例子1:

3

例子说明1:

因为在本题中,不要求回文子串连续,故最长回文子串为aba(或ada、aca)

解题思路

    这道题,乍一看,和LeetCode的第五题特别像,具体可参考博文:https://blog.csdn.net/weixin_42521211/article/details/87991695 

   分析:题干要求说“不要求子串连续“,再加上回文子串的定义,简单言之就是在回文字串中,除了子串最中间的那个字符外(偶数的话,中间的字符为两个)会出现奇数的情况,其余字符必然是偶数个数出现。因此,可每次截取从开始和结尾两个方向出现的同一个字符中间的字符串,得到子串的最大回文子串长度+2即为当前字符串的最大回文长度;继续重复操作,截取从开始和结尾两个方向出现的同一个字符中间的字符串,直到字符串的长度等于0或者1为止。根据分析,子串的操作过程和母串操作是一样的,因此,考虑使用递归实现,就再合适不过了!

    详细步骤如下:

    1) 查找字符串中,同一个字符在开始和结尾第一次出现的位置。既然是个查找问题,自然而然就想到了哈希算法,也就是字典存储字符串,字典的键为字符,值为字符每次出的下标(列表存储)。因为字符串每次截取后的子串,我们又需要重新建立字典,因此,这里我们将字符串的字典存储,用单独的一个函数来封装字符串的字典存储,一方面会使程序简单易懂,不太繁琐,另一方面,也方便后续的调用操作,避免重复工作;

    2)特殊情况的处理。这里所谓的特殊情况,指字符串为空或者只有一个字符时的操作,即直接返回该字符串的长度即可;

    3) 一般情况最长回文子串长度的求解。 首先,我们需要有一个变量来存储当前记录中的最长回文长度,也就是maxLen变量,初始值设为0;根据在分析部分的思考,遍历操作字典中的键,也就是当前遍历过程中得到的回文子串的长度记录,即变量temp。如果遍历到的键,也就是字符串中的字符对,如果下标差值小于等于1,则temp=temp+字符出现的个数;否则,即是说字符是成对出现的,则tem=temp+2,然后从当前字典键对应的值中得到开始的下标和结尾处的下标,截取字符串,然后重复进行上述操作,也就是程序递归实现。最后,每遍历完字典的一个键,判断当前记录的最大回文长度和当前遍历记录的最大回文子串的长度;

    4)返回结果。遍历完成之后,返回记录的最大回文子串的长度即可。

参考上述步骤,详细实现如下:


python具体实现

# 字典存储字符串
def strMemoryDict(string):
    """
    :type string: str
    :rtype: dict
    """
    strDict={}
    for i in range(len(string)):
        if string[i] not in strDict.keys():
            strDict[string[i]]=[i]       #如果字符未在字典键中,下标值用[i]
        else:
            strDict[string[i]].append(i)
    return strDict

def calMaxSubStr(string):
    """
    :type string: str
    :rtype: int
    """
    
    if len(string)<=1:      #特殊情况的判断
        maxLen = len(string)
        return maxLen

    maxLen = 0              # 存储最长回文子串长度
    strDict = strMemoryDict(string) # 字典存储字符串
    
    for i in strDict.keys():        # 遍历字典键
        temp = 0                    # 存储当前最长回文子串长度
        if strDict[i][-1]-strDict[i][0]<=1:#判断当前字符下标差值
            temp = temp+len(strDict[i])
        else:                              
            temp = temp+2
            left = strDict[i][0]    
            right = strDict[i][-1]
            string = string[left+1:right] # 截取子串
            temp += calMaxSubStr(string)  #遍历操作

        if temp>maxLen:                   #判断当前的回文子串长度和记录的最长回文子串长度
            maxLen = temp
    return maxLen
            
# 测试
string = input()
#maxLen = 0 
maxLen = calMaxSubStr(string)
print(maxLen)

题外话

    这个题,还是让自己好生一顿抓脑袋,感觉不难但程序结果就是不对,甚是蓝瘦。还是思路捋的不够清晰,所以,才会在程序上磕磕绊绊。

    上述程序,还有一个问题,自己本地的结果和答题环境的结果不一致,具体事例参看下图,通过再三本地环境的检验,自我确信自己的逻辑是对的。也就才衍生出的这篇博客!

    今天,其实还看了其他博客的实现方法,也有很多遍历的实现方法,但是在复杂度方面,自己思考的还是复杂度低很多,具体自己现在分析不是很清楚,但自己确信的是,现在的这种遍历方式,复杂度大大的进行了降低。哈希算法真的很厉害,最近一种的最大收获,哈希算法的入门使用!!!

             长路漫漫,砥砺前行!

 

python实现:回文字符串问题(快手2019年秋季校园招聘编程题算法B试卷(牛客网))_第1张图片

python实现:回文字符串问题(快手2019年秋季校园招聘编程题算法B试卷(牛客网))_第2张图片

你可能感兴趣的:(面试编程题python实现专栏,python,算法,面试题)