Leetcode No.3 无重复字符的最长子串

问题描述:

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

示例:

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

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

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

思路与分析:

1.brute-force的暴力方法:

思路:

枚举字符串的所有子串,判断每一个子串是否含有重复字符,若不含,计算当前的最优解ans = max(ans, len(s'))

复杂度:

判断是否含有重复字符需要用O(n)时间遍历子串;

生成子串 s(i,j) 的个数:每固定一个i,对应的 j 取值在 i+1 ~ j 之间, 子串总数为O(n^2)

故复杂度为O(n^3)

用这种算法实现的code在提交后会提示Timeout,必须进行优化

2.滑窗法+Hash Table

思路:

用字典来存储子串的元素:newset = {}

分别用i, j作为左右边界,拿来框住字符串从i到j那一段,想象这样的一个滑动的窗口,随着i、j的移动而滑动;我们就这样用 [ i, j ) 来表示字符串s的子串s(i , j),不必枚举所有子串,只需判断当前元素是否包含在滑窗中。

初始时i = j = 0,顺序扫描字符串s,判断当前元素 s[ j ] 是否包含在字典中:若包含,则 i ++, 相当于缩小滑窗,直到当前元素不再出现在滑窗中,同时删除字典中key为 s[ i ] 的元素;若不含,则 j ++,相当于当前元素加入滑窗中,同时将它加入字典。

同样的,每次纳入新元素时,求当前最优解 ans = max(ans, j - i)。

注意:为什么要使用字典?这是为了提高这一步的效率:判断当前元素是否包含在子串中

用列表或者字符串来存储元素时,每次查询操作都要O(n)的时间,这就造成了低效;Python的字典实质上是哈希表 ( Hash Table ),查询操作只需O(1)时间,这样就能优化算法了。

复杂度:

遍历字符串需要O(n)时间,遍历每个字符时的查询操作需要O(1)时间;

故复杂度为O(n)。

代码实现(Python):

class Solution(object):
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        n = len(s)
        i, j, ans = 0, 0, 0
        newset = {}
        while j < n:
            if s[j] not in newset:
                newset[s[j]] = 0
                j += 1
                ans = max(ans, j-i)
            else:
                del newset[s[i]]
                i += 1
        return ans

猜你喜欢

转载自blog.csdn.net/weixin_42095500/article/details/81461906