题目:
Given a string, find the length of the longest substring without repeating characters.
Examples:
Given "abcabcbb", the answer is "abc", which the length is 3.
Given "bbbbb", the answer is "b", with the length of 1.
Given "pwwkew", the answer is "wke", with the length of 3. Note that the answer 》must be a substring, "pwke" is a subsequence and not a substring.
解析:
面对此题,首先最容易想到的是使用暴力枚举,然而这会很容易超时,不可取。我们这里使用sliding window的思想,什么使sliding window呢,先这么分析。当我们在取字串的时候,需要两个定位的变量i和j,i代表子串的开头,j代表子串的结尾(j所指位置实际是子串最后字符的下一个字符,也就是j不在所取子串中)。
当我们在进行第一排搜寻的时候,i指向字符串的第一个字符,j指向第二个字符,这时候所取的子串就是第一个字符,只有一个字符,然后每次将j往后移动,直到发现所取子串出现重复的字符,如何判断是否有重复字符的方式也很简单,我们需要一个额外的HashSet,每当j后移,就将该字符添加进HashSet,以此来判断是否含有重复字符。当我们一发现出现重复的字符后,我们采取的措施就在这里与暴力枚举不同了,我们将i往后移,j保持不动,这之后再次检查是否重复,若还重复,重复上一步骤,直到i在j前面,这下一定不会重复,因为只有一个字符了。不重复之后,继续将j往后移,重复之前的步骤,重复了将i后移,不重复继续移动j。这将向一面窗户的两边,只会往一个方向移动,这个sliding window是不是很形象了呢。在上面的步骤中,只要是子串没有重复字符的时候,我们都要记录下从最开始到那个时候的无重复子串长度的最大值,这很好办,用到Math的max函数就行。总体思路是这样,下面来看代码:
class Solution {
public int lengthOfLongestSubstring(String s) {
Set<Character> c = new HashSet<Character>();#用来判断是否用重复字符的哈希集
int ans = 0;
int n = s.length();
int i = 0;
int j = 0;
while(i < n && j < n) {
if(!c.contains(s.charAt(j))){#无重复字符
c.add(s.charAt(j++));
ans = Math.max(ans, j-i);#子串的最大值
}else {#遇到了重复的字符
c.remove(s.charAt(i++));
}
}
return ans;
}
}