3. 无重复字符的最长子串
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:
输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:
输入: “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
解答:
一开始用的暴力法:通过两个for循环,算出每个字符开头的不含有重复字符的 最长子串 的长度。
public int lengthOfLongestSubstring(String s) {
int maxLength = 0;
//用List保存不重复最大字串
for (int i = 0; i < s.length(); i++) {
ArrayList<Character> characters = new ArrayList<>();
for (int j = i; j < s.length(); j++) {
if(characters.contains(s.charAt(j))){
break;
}
characters.add(s.charAt(j));
//看了其他的题解发现了Math.max(),底层也是用的三元运算符。
maxLength=characters.size()>maxLength?characters.size():maxLength;
}
}
return maxLength;
}
看了题解,知道了滑动窗口:
遍历字符串将字符依次存入Set,这个Set就是窗口,存入的字符就是子串。如果字符不是已存入的字符,就将该字符存入Set,如果遇到重复字符,Set就将头元素移除,再判断下一个字符。整个过程窗口的长度就是不重复字串的长度。
图示如下:
具体可参考此篇题解
public int lengthOfLongestSubstring(String s) {
int maxLength = 0;
//窗口的左右下标
int i = 0, j = 0;
//窗口
Set<Character> characters = new HashSet<>();
while (i < s.length() && j < s.length()) {
if (!characters.contains(s.charAt(j))) {
//不是重复字符,存入该字符,扩大窗口
characters.add(s.charAt(j));
j++;
maxLength = Math.max(j - i, maxLength);
} else {
//存在重复字符,移除窗口最左边的字符,缩小窗口
characters.remove(s.charAt(i));
i++;
}
}
return maxLength;
}