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

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

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

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

提示: 0 <= s.length <= 5 * 104 s 由英文字母、数字、符号和空格组成

解题:滑动窗口(python)

这道题作为leetcode题库里的第三题,相信很多同学都做过了,总得来说还是蛮简单的

正常有思路的话肯定第一反应就是想到滑动窗口,O(n)时间复杂度解决问题,没啥好说的

整个玄乎一点的 :

如果套个模版从普遍性的角度去解题

首先考虑最暴力的解法,把每一个字符作为起始字符,然后依次便利其后的字符,判断是否满足条件(对于一个给定的字符串来说,我们已知它的长度,并且每个起始字符独立无关,所以最外层是一个for循环。双指针通常由两个循环组成,一般情况下,如果前面两个条件有一个不满足,我们会选择while循环)

这道题里判断条件很简单,它的要求是不含有重复字符,所以去重是这道题的关键,提示给到了字符由英文字母、数字、符号和空格组成,考虑到的编码未知的情况下,就不用数组来计数了,正常的哈希集就行,python里的数据结构是集合。

相对于子列,子串一定是连续的,所以我们可以进一步划分子问题(把每个独立的字符取出作为起点是划分子问题的第一步),那么对于一个子串,为了保证它其中没有重复的字符,子串的子串也不能有重复字符,所以该条件可以用作剪枝(这其实是一个适用于dp的蛮经典的条件:在递归里,它是重复调用的基础;在递推里,它是简化运算的基础,不过这道题过于简单,题干条件直接当剪植用了)

最后的最后用个滑动窗口解决一下重复子问题(一开始,在整个解决问题的算法的架构上,每一个起始字符是独立的,它们是“同时”向后扩展,然后一步步判断是否满足条件,然后结束进程【就是所谓的剪植】,但是为了解决重复子问题,我们不能只对子串末尾进行剪植,而应该两头同时“剪”,这就是滑动窗口左指针移动的原因,也是这道题的另一个视角)


代码:

class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        sets = set()
        n = len(s)
        r, ans = -1, 0
        for l in range(n):
            if l != 0:
                sets.remove(s[i - 1])
            while r + 1 < n and s[r + 1] not in sets:
                sets.add(s[r + 1])
                r += 1
            ans = max(ans, rk - i + 1)
        return ans

代码详解:

这个代码cv力扣官方的,是人家精简之后的产物了

第一步:定义变量

首先前两个
1.定义哈希集合sets = set()
2.获取字符串长度.n = len(s)
没啥好说的

然后是
3.答案ans = 0用于计数
4.左指针left因为独立所以直接定义在外循环里

最经典的是右指针的定义r = -1
抛开python本身的索引特性,它这里定义的-1指的就是在第一个字符的左边,同时也是在最左指针的左边,这个不可能出现在运算过程中的状态说明了

运算过程中,左右指针是可以重叠的(虽然这道题中仅开始时存在)
右指针是运算的核心
确保了左右指针包括在子串内的同时,保证了边界条件不会出现混乱

这模版写的多的还好,没啥亮点,自己写的话思路就不简单有这么清晰了,总结一下算是给自己偷个懒(反正我自己经常反应不过来)

最后就是正常的循环嵌套,没啥好说的

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Grayson Zhang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值