Day9 最长不含重复字符的子字符串【双指针法】【待优化】【笔试已遇到】

题目:
请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。
【注意:子字符串 != 子序列,如"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

错误点:

  1. 避免不必要的变量创建(temp变量删除后,不再超时)
  2. python中string类变量可以直接使用len()函数,无需再转换成list(判断是否重复时)
  3. 子字符串长度的记录不完整。如当输入是"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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值