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.
思路:给定的string s, 那我们要找的longest substring without repeating characters可以用两个index i, j 来记录,即s.substring(i, j), substring中出现的character在boolean[256]数组中标记为true。我们使j不断往右挪动直到given string的末尾,在这过程中,当chars[j]没有出现在substring中时,加进当前的substring,当chars[j]出现在substring中时,我从substring的左边删除chracter 直到删掉当前chars[j]这个character,这时substring中便没有chars[j]这个元素,此时我们再将chars[j]加进substring,j继续往右移动,直到末尾。注意,当最长子串出现在s的末尾部分时,这时j == s.length()无法进入while循环来更新长度len,所以最后return时需要再更新一次以确保len是维持最长子串的长度。代码解法一是我自己写的(64ms, 38.16%),解法二是别人的代码(47ms, 92.67%),两个思路一样,但解法二在实现上有更多的优化。
代码如下:
解法一:
第一次提交wrong answer, 第二次提交才AC
public int lengthOfLongestSubstring(String s) {
if (s == null || s.length() == 0){
return 0;
}
int i = 0, j = 0;
int len = 0;
Set<Character> set = new HashSet<>();
while (j < s.length()){
if (!set.contains(s.charAt(j))){
set.add(s.charAt(j));
j++;
} else {
len = Math.max(len, j - i);
while (s.charAt(i) != s.charAt(j)){
set.remove(s.charAt(i));
i++;
}
set.remove(s.charAt(i));
i++;
}
}
return Math.max(len, j - i);
}
解法二:
public int lengthOfLongestSubstring(String s) {
int i = 0, j = 0;
int len = 0;
char[] chars = s.toCharArray();
boolean[] shown = new boolean[256];
while (j < s.length()){
shown[chars[j]] = true;
j++;
len = Math.max(len, j - i);
while (j < s.length() && shown[chars[j]]){
shown[chars[i]] = false;
i++;
}
}
return Math.max(len, j - i);
}