题目:
请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。
【注意:子字符串 != 子序列,如"pwwkew"中,最长字串是"wke",“pwke” 是一个子序列,不是子串】
leetcode原题链接
思路:
- 初始状态:左指针left=0,右指针right=0
- 终止条件:①右指针right遍历完字符串s
- 进入while循环
while循环的条件是while(right!=len(s)-1)
,子字符串的右指针到 字符串最右,此时字符串已遍历完。- right+=1,如果string[left:right+1]有重复字符,则left+=1,直至无重复
- 出while循环,return max_len=max(max_len,right-left+1)
代码1:
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
if len(s)==0:
return 0
if len(s)==1:
return 1
left,right=0,0
max_len=0
while(right!=len(s)-1):
right+=1
for i in s[left:right+1]:#判断子字符串中是否有 重复字符
if s[left:right+1].count(i)>1:#若有
left+=1#left左移一位,直至无重复字符,才会运行下一行代码
max_len=max(max_len,right-left+1)#遍历过的【无重复子字符串】中len最大的值 和 当前正在遍历的【无重复字符串】的len值比较,取max
return max_len#字符串s遍历完成,返回max_len
两个if语句,是因leetcode的两个特殊测试用例而增设
判断子字符串中是否有 重复字符的方法
-
法一:
for i in s[left:right+1]:#判断子字符串中是否有 重复字符 if s[left:right+1].count(i)>1:#若有 left+=1#left左移一位,直至无重复字符,才会运行下一行代码
-
法二:
while len(s[left:right+1])!=len(set(s[left:right+1])): left+=1
代码2:
代码2采用法二进行【字符串重复判断】
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
if len(s)==0:
return 0
if len(s)==1:
return 1
left,right=0,0
max_len=0
while right<len(s)-1:
right+=1
while len(s[left:right+1])!=len(set(s[left:right+1])):
left+=1
max_len=max(max_len,right-left+1)
return max_len
代码1(左)和代码2(右)运行效果
-------------------------笔试遇到该题,记录--------------------------------------
当时写的代码如下,考后在leetcode提交 显示运行超出时间限制
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
if len(s)==0:
return 0
if len(s)==1:
return 1
n=len(s)
left,right=0,0
now_sublen=0
while right<n:
right+=1
temp=s[left:right]#加了这行后超出时间限制
if len(list(temp))>len(set(temp)):
now_sublen=max(now_sublen,right-left-1)
while len(list(temp))>len(set(temp)):
left+=1
return now_sublen
错误点:
- 避免不必要的变量创建(temp变量删除后,不再超时)
- python中string类变量可以直接使用len()函数,无需再转换成list(判断是否重复时)
- 子字符串长度的记录不完整。如当输入是"au"时,正确输出为2,该代码(删除temp后)会输出0。所以,跳出第二个while循环,即当前子字符串不重复时,记录此时的len,并得到此时的maxlen。原代码两次判断是否重复,先将重复前的子字符串长度记录下来,和left右移后再次重复前的子字符串比较大小,保留较大值,若此后子字符串不重复,则未记录到。
关于第三个错误:
问题:原代码记录的是每次子字符串重复前的最大长度,无法得到正确结果。
正解:不重复时,每当right指针右移一格,持续记录当前子串的长度len;若right右移至【当前字符串s[left:right]重复的情况】,left持续右移,直至不重复时,再记录当前不重复子串的长度len,与先前最大子串len比较,取max。
修改后代码可成功提交:
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
if len(s)==0:
return 0
if len(s)==1:
return 1
n=len(s)#这里也可以不用新建变量n,后面只有一处用到
left,right=0,0
now_sublen=0
while right<n:
right+=1
while len(s[left:right])>len(set(s[left:right])):
left+=1
now_sublen=max(now_sublen,right-left)
return now_sublen