无重复字符的最长子串
这是我的第一篇博文,创建这个分类是因为个人比较喜欢研究算法,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,否则返回false26 */27 public boolean isReapt(String s, int front, int rear) {28 Setset = 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 Setset = 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 }