LeetCode 3. 无重复字符的最长子串(中)

3. 无重复字符的最长子串(中)

题目

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

示例

输入: "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
     请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

考察知识点

队列、滑动窗口

核心思想

遍历字符串,找到不重复的部分,记录下来,输出最长的那一个。

图示

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WleV1bRr-1583596773087)(http://q3q41dfs4.bkt.clouddn.com/20ahe.gif)]

Python代码

class Solution:
    def lengthOfLongestSubstring(self, s):
        max_length = 0  # 开始位置
        d = {}  # 保存字符出现位置
        start = 0  # 当前最大字串的开始位置 也就是滑动窗口的左边缘
        for i in range(len(s)):
            if s[i] in d and start <= d[s[i]]: 
                # 如果该字符串出现过 且 当前最大字串的开始位置(start)小于等于该字符串之前出现的位置
                start = d[s[i]] + 1  # 当前重复字符串上一次出现位置的下一个位置 被设置为 新的最大字串搜寻开始位置 也就是滑动窗口的左边缘
            max_length = max(i-start+1, max_length)  # i-start+1(当前位置(i)减去滑动窗口左边缘的间距,也就是新字串的长度)
            d[s[i]] = i  # 全部计算完成之后,更新这个字串出现位置。
        return max_length

print("leet code accept!!!")
cases = ["abcabcbb", "bbbbb", "pwwkew", "aabaab!bb", "nfpdmpi", "dvdf"]
answer = ["abc", 'b', 'wke', "ab!", 'nfpdm', 'vdf']

if __name__ == "__main__":
    solution = Solution()
    for i in range(len(cases)):
        print(solution.lengthOfLongestSubstring(cases[i])==len(answer[i]))
  • 另一个版本
class Solution3:
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        from collections import defaultdict
        d = defaultdict(int)  # defaultdict本质就是一个dict
        l = ans = 0  # l是当前的最大长度
        for i,c in enumerate(s):
            while l > 0 and d[c] > 0:  # l>0说明不再是第一个字符 d[c]>0说明这个字符不是第一次出现
                # 下面这段while循环 会执行l次且直到将c的次数减为0 
                # 实际上就是把队列左边的元素移出去 平移整个
                d[s[i-l]] -= 1
                l -= 1  # 当前长度减去1
            d[c] += 1  # 记录最新发现的字符
            l += 1  # 记录最新长度
            ans = max(ans, l)
        return ans

类似问题

  1. 最小覆盖子串
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值