两个相同字符之间的最长子字符串

标签: 哈希表 字符串

难度: Easy

给你一个字符串 s,请你返回 两个相同字符之间的最长子字符串的长度 计算长度时不含这两个字符。如果不存在这样的子字符串,返回 -1

子字符串 是字符串中的一个连续字符序列。

 

示例 1:

输入:s = "aa"
输出:0
解释:最优的子字符串是两个 'a' 之间的空子字符串。

示例 2:

输入:s = "abca"
输出:2
解释:最优的子字符串是 "bc" 。

示例 3:

输入:s = "cbzxy"
输出:-1
解释:s 中不存在出现出现两次的字符,所以返回 -1 。

示例 4:

输入:s = "cabbac"
输出:4
解释:最优的子字符串是 "abba" ,其他的非最优解包括 "bb" 和 "" 。

 

提示:

  • 1 <= s.length <= 300
  • s 只含小写英文字母

Submission

运行时间: 23 ms

内存: 15.9 MB

class Solution:
    def maxLengthBetweenEqualCharacters(self, s: str) -> int:
        d={}
        ans=-1
        arrs=list(s)
        for i,c in enumerate(arrs):
            if c not in d:
                d[c]=i
                
            else:
                ans=max(ans,i-d[c]-1)
                 
        return ans

Explain

此题解的思路基于字典来记录每个字符首次出现的位置。遍历字符串中的每个字符,如果字符是首次出现,则在字典中记录该字符和它的索引。如果字符已经在字典中,说明之前已经遇到过一次,此时计算当前位置与首次出现位置之间的字符数(即两个相同字符之间的最长子字符串的长度),并更新最大长度。最后返回记录的最大长度。

时间复杂度: O(n)

空间复杂度: O(1)

class Solution:
    def maxLengthBetweenEqualCharacters(self, s: str) -> int:
        d = {}  # 字典用于存储每个字符首次出现的索引
        ans = -1  # 初始化答案为-1,适用于没有任何两个相同字符的情况
        arrs = list(s)  # 将字符串转换为字符列表
        for i, c in enumerate(arrs):  # 遍历字符及其索引
            if c not in d:  # 如果字符c是首次出现
                d[c] = i  # 记录字符c的索引
            else:  # 如果字符c之前已经出现过
                ans = max(ans, i - d[c] - 1)  # 计算两个相同字符之间的最长子字符串长度,更新最大值
        return ans  # 返回最大长度

Explore

在这个算法中,字典存储的是每个字符首次出现的索引,并且这个索引在后续的遍历中不会被更新。这是因为我们的目标是找到两个相同字符之间的最长子字符串,这涉及到计算从首次出现位置到当前位置之间的距离。如果我们更新了字符的索引,那么我们将丧失首次出现的位置信息,从而无法正确计算出两次出现之间的距离。因此,即使字符多次出现,我们也保持字典中该字符索引的值不变,始终指向该字符在字符串中首次出现的位置。

在这个算法中,答案初始化为-1是为了处理那些没有任何两个相同字符的字符串的情况。如果字符串中的所有字符都是唯一的,那么就不存在两个相同字符之间的子字符串,因此最长子字符串的长度应该是不存在的,即返回-1。如果初始化为0,在字符串中没有重复字符的情况下,返回0将错误地暗示存在长度为0的子字符串,这并不准确。因此,初始化为-1是为了在特殊情况下提供正确的返回值,并明确表示没有找到有效的子字符串。

当处理的字符串中的所有字符都是不同的,字典将记录每个字符的索引,但由于没有任何字符会重复出现,字典中的索引不会被用于计算任何子字符串的长度。因此,字典的存在仅用于记录首次出现的位置,而由于没有重复的字符触发长度计算的条件,初始化的答案-1将不会被任何计算所修改。这样,算法最终返回-1,确切地反映了这种情况下的正确结果:没有两个相同字符之间的子字符串。