3. 无重复字符的最长子串
中等
给定一个字符串 s
,请你找出其中不含有重复字符的 最长 子串 的长度。
示例 1:
输入: s = "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
暴力直观解法一:
思路: 手动看题: -> O -> 不重复字符? os: 有没有这样一种数据结构....,有的兄弟有的。队列报你身份证了。 维护一个队列,每次往队列中加入元素,就去看看队列中是否有一个相同的元素已经在里面了,如果有,就把元素从前往后进行结算,再将该元素加入队列中,以此类推,得到最长子串.
class Solution {public int lengthOfLongestSubstring(String s) {Queue<Character> queue = new LinkedList<>();int n = s.length();int maxlen = 0;int len = 0;for(int i = 0; i < n; i ++){char c = s.charAt(i);// 判断队列中是否存在这么一个元素boolean std = queue.contains(c);// 还存在重复元素则把前面的不断进行移除if(std){while(queue.contains(c)){queue.remove();len--;}}// 移除完了就可以加入进行 queue.add(c);len ++;maxlen = Math.max(maxlen, len);}return maxlen;} }
执行用时分布 18ms 击败10.70%
神魔 才10.70% OVO。观察上述代码主要耽误我时间的地方就是检查这个元素 queue.contains(c); -> O(n)。神魔在我的代码中怎么能有这种坏东西。
不服,再来
解法二: 用Set来维护这些元素(set.contains(c)的时间复杂度为O(1)),那怎么保留队列的性质呢? 我们只需要在加入元素的时候一直加加加,加到厌倦(出现了重复元素),然后移除的时候只需要移除掉那个重复元素就行
class Solution {public int lengthOfLongestSubstring(String s) {Set<Character> set = new HashSet<Character>();int len = s.length();int right = 0;int maxNumber = 0;for(int i = 0; i < len; i ++){// 除了第一次加入元素外,其它都是上一轮加到重复了才会停止,所以将上一个字符移除if(i != 0) set.remove(s.charAt(i - 1)); // 加加加,加到厌倦while(right < len && !set.contains(s.charAt(right))){set.add(s.charAt(right));right ++;}maxNumber = Math.max(maxNumber, right - i);}return maxNumber;} }
6ms击败 67.99%