给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是"abc",所以其长度为 3。示例 2:
输入: "bbbbb" 输出: 1 解释: 因为无重复字符的最长子串是"b",所以其长度为 1。示例 3:
输入: "pwwkew" 输出: 3 解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。 请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
一开始的思路:
遍历字符串,从每一位开始,寻找最长无重复串。重复了就break。
class Solution:
def lengthOfLongestSubstring(self, s):
"""
:type s: str
:rtype: int
"""
max_length = 0
for i in range(len(s)):
myset = set()
for j in range(i, len(s)):
if(s[j] in myset):
break
else:
myset.add(s[j])
max_length=max(len(myset), max_length)
return max_length
个人觉得值得注意的地方:
1. 边界条件:j从i开始。我一开始写的时候是在初始化myset的时候就放好s[i],j从i+1开始,但是这样遇到字符串长度为1等情况就会有问题,上一次也有这种问题,总的来说最好不要让第一个元素特殊化;i从len(s)停止。
2. 更新max_length的位置:起初我写在break之前,但严格来说程序是可以不执行到那里的。好吧,这个问题很简单,不值得注意。
3. 一些输入:"bbbbbb", "b"
复杂度应该是O(n^2)
类似的思路,还可以有个O(n)的写法。
用了滑动窗口的方法。当遇到重复时,i右移并把原s[i]去掉,然后再继续从j处操作。这样就免了从i到j这已经检查过的部分重复进行。
class Solution:
def lengthOfLongestSubstring(self, s):
"""
:type s: str
:rtype: int
"""
max_length = 0
i=0
j=0
myset = set()
while(i<len(s) and j<len(s)):
if (not s[j] in myset):
myset.add(s[j])
j = j+1
max_length = max(max_length, j-i)
else:
myset.remove(s[i])
i = i+1
return max_length
更新max_length的位置:在重复的时候更新不更好吗?但是这样对于长度为1的不适用。
当然,可以强行改成如下:
class Solution:
def lengthOfLongestSubstring(self, s):
"""
:type s: str
:rtype: int
"""
max_length = 0
i=0
j=0
n=len(s)
myset = set()
if (n==0 or n==1):
return n
while(i<n and j<n):
if (not s[j] in myset):
myset.add(s[j])
j = j+1
max_length = max(max_length, j-i)
else:
myset.remove(s[i])
i = i+1
return max_length
速度确实变快了....从188ms到112ms