Leetcode 3:无重复字符的最长子串(最详细解决方案!!!)

给定一个字符串,找出不含有重复字符的最长子串的长度。

示例:

给定 "abcabcbb" ,没有重复字符的最长子串是 "abc" ,那么长度就是3。

给定 "bbbbb" ,最长的子串就是 "b" ,长度是1。

给定 "pwwkew" ,最长子串是 "wke" ,长度是3。请注意答案必须是一个子串"pwke"子序列 而不是子串。

解题思路

首先想到的解决思路是先遍历整个字符串,然后对遍历到的每个字符后的字符做处理(检查是否有重复元素),我们通过建立一个空的字符串,如果检查的字符在这个空的字符串中没有的话,我们将他加入这个空字符串中,并且记录这个空字符串的长度。

class Solution:
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        maxLength = 0
        for i,_ in enumerate(s):  #这里没有使用range函数      
            count = 0
            usedChar = str()
            for j in s[i:]: 
                if j not in usedChar:
                    usedChar += j
                    count += 1
                    if maxLength < count:#这里没有使用max函数
                        maxLength = count
                else:                   
                    break
        return maxLength

上述代码中我没有使用注释中的做法,是因为那样做消耗的时间会增加很多(尤其这里如果使用max函数操作会极大地增加时间消耗,但是有的时候使用max函数速度会更快,暂时不清楚原因),大家可以自己测试一下。

另外,我们通过分析可以知道这个算法最差情况的时间复杂度是O(n^2)级别的,这显然不是我们想看到的。我们分析一下这个算法的缺陷在哪?

p w w k e w
i
    j
usedChar = pw

j移动到第二个w时,这个时候j in usedChar,那么我们跳出循环。接着

p w w k e w
  i
    j
usedChar = w 

这个步骤其实是没有用的,因为去掉一个元素后,不可能比之前的元素更长了。我们可以直接跳到重复元素之后开始新的循环。

扫描二维码关注公众号,回复: 1549107 查看本文章
p w w k e w
    i
    j
usedChar = w 

我们这里借用之前Leetcode 1:两数之和中使用hash表的思想

class Solution:
    """
    :type s: str
    :rtype: int
    """
    def lengthOfLongestSubstring(self, s):
        start = maxLength = 0
        usedChar = {}
        for index, char in enumerate(s):
            if char in usedChar and start <= usedChar[char]:
                start = usedChar[char] + 1
            else:
                maxLength = max(maxLength, index - start + 1)
            usedChar[char] = index
        return maxLength

这种解法速度很快,时间复杂度是O(n)级别,但是空间复杂度也是O(n)级别。这也是我认为这个题目目前为止最精彩的回答!!!

当然这个问题,我们也可以使用Leetcode 209:长度最小的子数组中提到的滑动窗口思想。

class Solution:
    """
    :type s: str
    :rtype: int
    """
    def lengthOfLongestSubstring(self, s):
        l = 0
        r = 0
        maxLength = 0
        s_len = len(s)
        usedChar = [0] * 256 #通过符号表记录符号出现次数
        while l < s_len:
            if r < s_len and usedChar[ord(s[r])] == 0:
                usedChar[ord(s[r])] += 1
                r += 1
            else:
                usedChar[ord(s[l])] -= 1
                l += 1

            maxLength = max(maxLength, r - l)

        return maxLength

这个解法虽然比前面的慢,但是空间复杂度是O(256)级别,而时间复杂度同样是O(n)级别。

该问题的其他语言版本添加到了我的GitHub Leetcode

如有问题,希望大家指出!!!

猜你喜欢

转载自blog.csdn.net/qq_17550379/article/details/80547777