3. Longest Substring Without Repeating Characters
Medium
Given a string, find the length of the longest substring without repeating characters.
Example 1:
Input: "abcabcbb"
Output: 3
Explanation: The answer is "abc"
, with the length of 3.
Example 2:
Input: "bbbbb"
Output: 1
Explanation: The answer is "b"
, with the length of 1.
Example 3:
Input: "pwwkew" Output: 3 Explanation: 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.
解法一:暴力破解
//Brute Force
public static int lengthOfLongestSubstring(String s) {
int max = 0 ;
Set<Character> set = new HashSet<>() ;
for(int i=0; i<s.length(); i++) {
for(int j=i; j<s.length(); j++) {
char ch = s.charAt(j) ;
if(set.contains(ch)) {
max = Math.max(max, set.size()) ;
set.clear();
break ;
} else {
set.add(ch) ;
}
}
}
return Math.max(max, set.size()) ;
}
解法二:滑动窗口
1. 分别设置两个快慢指针i和j,起始位置均在0位;i为慢指针,j为快指针
2. 依次遍历字符串s中的每个字符ch,并设置集合Set用于缓存当前快慢指针之间的子字符串
1)如果ch不在set中,说明当前子字符串还未出现在快慢指针之间的字符串中,所以该子字符串还有进一步扩大的可能;所以快指针j++;i保持不动;且与当前保持的最大值max做比较,记录最大值;
2)如果ch在set中,说明当前字符已在快慢指针之间的字符串中出现过了,所以当前子字符串遍历结束,(如果继续遍历则会在子字符串中出现重复字符);此时需要慢指针i右移一位+1,开始重新计算子串,但需要将移动之前的所指字符从set中删除掉;且快指针j不动。
3)重复步骤1)2)直到i或者j到达字符串末尾为止
4)max记为最长子字符串长度
//Sliding Window
public static int lengthOfLongestSubstring(String s) {
int n = s.length();
Set<Character> set = new HashSet<>();
int ans = 0, i = 0, j = 0;
while (i < n && j < n) {
// try to extend the range [i, j]
if (!set.contains(s.charAt(j))){
set.add(s.charAt(j++));
ans = Math.max(ans, j - i);
}
else {
set.remove(s.charAt(i++));
}
}
return ans;
}
解法三:滑动窗口(优化版)
// Sliding Window Optimized
public static int lengthOfLongestSubstring(String s) {
int n = s.length(), ans = 0;
Map<Character, Integer> map = new HashMap<>(); // current index of character
// try to extend the range [i, j]
for (int j = 0, i = 0; j < n; j++) {
if (map.containsKey(s.charAt(j))) {
i = Math.max(map.get(s.charAt(j)), i);
}
ans = Math.max(ans, j - i + 1);
map.put(s.charAt(j), j + 1);
}
return ans;
}