最近在刷leetcode,遇到了这题,
最开始想的是要暴力破解,写出了复杂度o(n²)的解法,不太满意,看了题解发现了滑动窗口这种算法,豁然开朗
先上代码
复杂度只有o(n)
思路就是我们定义一个map数据结构,通过不停的计算子串的起始位置和结束位置来计算出我们想要的结果
例如
我们输入一个字符串 “abcabbacds”,可以看出最长子串是bacds长度是5,那么代码运行过程中发生了什么呢?
可以看出代码中前三次循环"abc"时map w中不含重复的字符,
那么此时的窗口起始位置‘a’也就是j=0,结束位置也就是’c’ i= 2那么其长度就是i结束位置减起始位置+1, i-j+1=3。
到了第四次循环i=3 s[3]=a,此时w中已有一个a字符串故而重复,那么应该更新子串的起始位置j=w[s[i]]+1可能你会有疑问为什么要加1,因为w[s[i]]的值也就是第一个字符串a已然与第二个重复,那么下一个子串长度的起始位置自然是a的位置+1。并且,如果当前j的位置要是小于上一次循环的j的值,那么以上一次循环的j值为子串起始位置,为什么呢,因为字符串从左往右遍历,如果在一个位置值大的字符串之前发现了重复值那么还是要以后面的重复值为子串起始位置。有点点绕,但是应该不难理解。
然后下一步更新最大子串的值,也就是上一次的i-j+1的值与这一次i-j+1的值比较,取大的那个。重复上面逻辑我们即可得到无重复最长子串的值。
总结:
其实,我们通过维护字符串的起使长度j与结束长度i即可,i到j的长度就像一个不断变化的窗口,有重复值时,我们计算出新的窗口起始位置,并得到此时的窗口长度并记录下来与下一次长度比较,即可得出最长的那个窗口。有理解错误的地方欢迎指正~