无重复字符的最长子串-双指针

无重复字符的最长子串 双指针解法

题目描述

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

解题思路

做这道题的时候第一个想到的是动态规划,因为与寻找最长回文子序列有些相似,想着用f[i][j]来表示下标i到下标j子串的状态。但在做的过程当中,发现必须存储当前已经遍历过了哪些字符,而用f[i][j]存储子状态遍历过哪些字符好像在空间上面会开辟大量的空间,于是选择另寻他路。

最容易的想法是暴力求解,用两个指针ij。依次增加i的值,每次增加i的值时ji+1遍历到字符串的结尾,这样的时间复杂度是 O ( N 2 ) O(N^2) O(N2),对于长一些的测试用例多半是通不过的,于是想办法进行优化,想想哪些地方可以直接跳过。

分析后发现三点技巧:

  1. 如果 s i ⋯ s j s_i\cdots s_j sisj没有重复,而 s j + 1 s_{j+1} sj+1与其中的某一个重复了,那么后续的字符就不用再遍历,直接进行下一轮迭代
  2. 假设 s j + 1 s_{j+1} sj+1是与 s i ⋯ s j s_i\cdots s_j sisj中的 s k ( i < k < j ) s_k(i<k< j) sk(i<k<j)重复了,如果我们下一轮迭代从 s i + 1 s_{i+1} si+1开始迭代,那么必然又会遇到 s j + 1 s_{j+1} sj+1 s k s_k sk重复的情况。又因为我们是要求最大的无重复子串长度,所以这必然会比原来从 s i s_i si开始的子串更短,因此这样的迭代是没有意义的,我们可以直接将i跳到k+1来防止这样的无用迭代
  3. 在发现重复字符之前的字符都是不重复的,如果我们每次都将j退回到i+1那么就会将以前已经知道的不重复的字符又重新判断一次,这也无疑是无用功。因此,我们根本就没有必要将j往回退,当i的值更新后j继续进行判断即可

经过这三点技巧,可以发现ij都是一直在往前走的,也就是说当j==len(s)的时候整个算法就结束了,整个算法的时间复杂度降到了 O ( N ) O(N) O(N)

实现代码

def lengthOfLongestSubstring(s):
        n = len(s)#获取字符串长度
        if not n:
            return 0
        max_len = 1#至少长度为一,因为单个字符是无重复的
        i,j=0,1
        while j<n:
            index = s[i:j].find(s[j])#找到该字符在已检测子串中的位置
            if index == -1:#表示没有重复出现过
                if j - i + 1 > max_len:
                    max_len = j - i + 1
                j+=1
            else:#重复出现
                i += index+1
        return max_len
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值