LeetCode第三题:无重复字符的最长子串
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串的长度。
示例 :
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
根据上一道题“找到字符串中所有的异位词”http://(https://social.citicpru.com.cn/bbs/#/thread?topicId=57)的经验, 这道题又是做字符串字母出现次数的判断,
所以可以想到需要使用的方法是滑窗滑窗滑窗!!!
一旦确定了这道题需要用到滑窗算法,那么figure out思路出来应该不难。
做这道题的时候,我第一次想到的双重for循环思路,也就是定义一个int i,再定义一个int j,分别作为数组s最左侧的指针和最右侧的指针组成滑窗,不断获取s的第i个元素到第j-1个元素组成的子串。
For循环思路:
第一层for循环i:i会遍历取从s的第0个元素一直到s的最后一个元素
第二层for循环j:在上层循环确定i的值后,j会遍历从s的第i+1个元素到s的最后一个元素,由此可以不断的枚举s的子串。
每当获取到子串,我们判定一下,在j遍历到下一个元素时获取的值是否已经在当前的子串中存在,如果是,结束本次j循环,直接让i遍历下一个值。(因为此时j就算继续往后走,子串中也已经存在至少两个相同的字符了。)如果否,则获取j遍历到下一个元素时产生的新的子串的长度。i和j的两层遍历都完成后,取最长的那个子串的长度。
这个思路比较简单,代码如下。
复制
对于一般的字符串,这个方法是完全OK的,但是根据前面几次被捶打的经验,在Leetcode上使用双重For循环这种复杂度为O(n²)的方法是100%无法通过提交的,因为LeetCode的测试用例一定会给你一个巨变态的超长数组,对于超长数组使用两层For循环的时间复杂度太高了,一定会超时的。所以双重For循环,对于LeetCode来说,就是不够优雅的暴力解法。
既然无法使用嵌套For循环,我们就要思考复杂度更低,效率更高的方式。如果for循环只能用一次来遍历外层,只能遍历出每个潜在子串首字符在s中的序号i(叫左指针好了),但内层我们仍然需要不断向后遍历一个右指针rpointer,才能形成一个起始为s的第i个元素,末尾为s的第rpointer-1个元素的子串,用于判定s的第rpointer个元素的值是否已存在于当前子串中。
不能用For循环,那么就用While循环好了,在循环是加上条件:rpointer的最大值不能超过s的长度,以及每次获取的s的第rpointer个元素的值不存在于上次循环产生的子串中,否则本轮对右指针的循环结束,让上层循环的左指针向右移动一位。
For循环+while循环的代码:
复制
再次取Leetcode提交,成了!
然而只击败了18%的用户。。。。。哎
但是好歹通过了。
看了下官方答案,大致思路一致,但是使用了一个新的hashset来记录子串,以此来进一步提升效率。
晚安。