无重复字符的最长子串
无重复字符的最长子串
这是我的第一篇博文,创建这个分类是因为个人比较喜欢研究算法,Ok,Talk is cheap,Let's go,I will show you my code.
题目描述如下:
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其
长度为 3。
示例 2:
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b"
,所以其长度为 1。
示例 3:
输入: "pwwkew" 输出: 3 解释: 因为无重复字符的最长子串是"wke"
,所以其长度为 3。 请注意,你的答案必须是 子串 的长度,"pwke"
是一个子序列,不是子串。
我们来分析一下这个问题,要想找到给定字符串的无重复字符的最长字串的长度,那要对字符串进行遍历,第一种思路是:遍历字符串中的所有字符,并把它们存入set集合中,在存入之前先判断set中是否已经
包含该元素,若包含则返回true,否则返回false,并存入set中。下面我们看下代码:
1 /** 2 * 3 * @param s 输入的字符串 4 * @return 最长不重复字串的长度 5 */ 6 public int lengthOfLongestSubstring(String s) { 7 int length = s.length();//取得字符串的长度 8 int size = 0; 9 for (int i = 0; i < length; i++) { 10 for (int j = i + 1; j <= length; j++) { 11 if (!isReapt(s, i, j)) { 12 size = Math.max(size, j - i); 13 } 14 } 15 } 16 17 return size; 18 } 19 20 /** 21 * 22 * @param s 输入的字符串 23 * @param front 指向字符串的头部 24 * @param rear 指向字符串的尾部 25 * @return 若重复则返回true,否则返回false 26 */ 27 public boolean isReapt(String s, int front, int rear) { 28 Set<Character> set = new HashSet(); 29 for (int i = front; i < rear; i++) { 30 Character c = s.charAt(i); 31 if (set.contains(c)) { 32 return true; 33 } 34 set.add(c); 35 } 36 return false; 37 }
上面那种解法虽然能解决问题,但过于笨重,那有没有一种办法可以更快呢?答案是有的。我们用到滑块的思想。代码如下:
1 /** 2 * 3 * @param s 传入的字符串 4 * @return 最长不重复字串的长度 5 */ 6 public int lengthOfLongestSubstring(String s) { 7 int length = s.length();//取得输入字符串的长度 8 Set<Character> set = new HashSet<>(); 9 int size = 0; 10 int front = 0;//滑块头 11 int rear = 0;//滑块尾 12 while (front < length && rear < length) { 13 14 if (!set.contains(s.charAt(rear))){//如果set中不包含当前元素,就把它添加到set中,并更新ans值 15 16 set.add(s.charAt(rear++)); 17 size = Math.max(size, rear - front); 18 19 } 20 else { 21 22 set.remove(s.charAt(front++));//如果set中包含当前元素,就通过逐一移动i的方式删除set内的元素, 23 //直到set.contains(s.charAt(j))条件不满足为止 24 } 25 } 26 return size; 27 }