具有非重复字符的最长子字符串

时间:2018-01-19 14:13:54

标签: python string algorithm data-structures

我正在尝试解决找不到给定字符串中没有重复字符的最长子字符串的问题。

class Solution(object):
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        start = 0
        mlen = -1
        cur_ = {}
        cur = 0

        while(start<len(s) and cur<len(s)):
            if s[cur] in cur_ and cur_[s[cur]] >= start:
                if cur - start > mlen:
                    mlen = cur - start
                start = cur_[s[cur]] + 1    
                cur_[s[cur]] = cur            
            else:
                cur_[s[cur]] = cur
                if cur - start > mlen:
                    mlen = cur - start
            cur = cur + 1            
        return mlen

x = Solution()
print(x.lengthOfLongestSubstring("abababcdef"))

我想我正在解决它:

遇到重复的字符时,启动一个新的子字符串。

但我没有得到正确的答案?

在上面的示例中,输出为5,而正确答案为6.

但对于这种情况:

打印(x.lengthOfLongestSubstring(&#34;巴&#34))

输出正确,即2。

不确定为什么我没有失败?感谢。

4 个答案:

答案 0 :(得分:2)

我已经稍微更改了你的函数,以返回唯一字符的最长子字符串,而不仅仅是它的长度。如果你想要长度 - 你总是可以从字符串中得到它。

def get_longest_substring(input):
    """
    :type input: str
    :rtype: str
    """

    current = []
    all_substrings = []
    for c in input:
        if c in current:
            all_substrings.append(''.join(current))
            cut_off = current.index(c) + 1
            current = current[cut_off:]
        current += c
    all_substrings.append(''.join(current))

    longest = max(all_substrings, key=len)
    return longest

longest = get_longest_substring("abababcdefc")
print(longest, len(longest))

代码遍历每个char构建一个char数组。

如果它在数组中找到了一个字符,它会保留一个数组的副本,切断它的开头直到该字符并继续构建它。

最后,它选择找到的最长的子串并返回它。

答案 1 :(得分:1)

您在else分支中错误地更新if s[cur] in cur_ and cur_[s[cur]] >= start: start = cur_[s[cur]] + 1 else: mlen = max(mlen, cur - start + 1) cur_[s[cur]] = cur cur = cur + 1 ,您忘记添加当前字符。此外,当您遇到重复时,您无需更新{{1}}:

{{1}}

答案 2 :(得分:1)

我可以建议你这个简单的算法:

1。将所有变量设置为空。

字符串中每个字母ch的

2。

2.1。检查chrrent found子字符串的dict中是否存在 ch

如果确实 - 检查是否符合标准。子字符串长于max(maxSubStr初始化为&#34;&#34;)?,确实 - 切断了字符串。最大的子字符串使用值 ch 设置currrent找到的子字符串的dict,并将当前子字符串设置为 ch

如果它没有 - ch 添加到currrent找到的子字符串的dict中。并且结束了这个&#39;子串与 ch

3. 返回当前子字符串中最长的字符串和最大字符串的长度。

class Solution(object):

def lengthOfLongestSubstring(self, s):
    """
    :type s: str
    :rtype: int
    """

    curSubStr = ""
    curSubStrDict = {}
    maxSubStr = ""
    for ch in s :
        if ch in curSubStrDict :
            if len(maxSubStr) < len(curSubStr):
                maxSubStr = curSubStr
            curSubStrDict = {}
            curSubStrDict[ch] = ch
            curSubStr = ""+ch

        else :
            curSubStrDict[ch] = ch
            curSubStr += ch

    return len(curSubStr) if len(curSubStr) > len(maxSubStr) else len(maxSubStr)

x = Solution()
print(x.lengthOfLongestSubstring("abcaabccdefgfgh")) # 5 = |cdefg|
print(x.lengthOfLongestSubstring("abababcdef")) # 6 = |abcdef|

就像在数组中找到最大元素一样,我们&#34;迭代&#34; (不是实际迭代)-substrings而不重复char-并保存最长的。

当我们检测到包含在当前子字符串中的char时,会发生迭代。比我们迭代到下一个子串。

答案 3 :(得分:0)

虽然您可以通过在每次迭代时递增标记来跟踪字符串中的位置,但使用嵌套的for循环会更简单:

s = "abababcdef"
long_run = max({s[i:b] for i in range(len(s)) for b in range(len(s)) if len(set(s[i:b])) == len(s[i:b])}, key=len)

使用set comprehension,代码首先使用嵌套for循环查找所有可能的子字符串。每个for循环生成字符串长度范围内的所有值,因此无需改变上限和下限。该理解过滤所有包含至少一个重复值的子串。为此,代码使用set函数删除所有重复项,从而检查子串字符串的相等长度到一个集合以及原始子字符串的长度。最后,max函数应用于集合,通过len的键找到集合中最长的子字符串。

输出:

'abcde'