题目:给定一个字符串,找出其中不含有重复字符的最长子串的长度
- 示例
输入 | 输出 |
---|---|
abcabcbb | 3 |
bbbbb | 1 |
pwwkew | 3 |
注:答案必须是 子串 的长度,“pwke” 是 “pwwkew” 的一个子序列,不是子串。
-
解题思路:
i、j 分别表示开始和结束的索引,用 i、j “遍历”整个字符串,寻找没有重复字符的子串。如果找到的没有重复字符的子串长度大于最长子串 longestStr 的长度,则更新 longestStr。
需要注意以下几个问题:
(1)字符串 s 可能为空字符串
(2)字符串 s 可能每个字符都相同 -
代码如下:
public static int lengthOfLongestSubstring(String s) {
// 如果为空字符串“”,则直接返回 0
if(s.length() == 0)
return 0;
String longestStr = ""; // 用于表示最长子串
int i = 0, j = i + 1;
while (i < j) {
if (i < s.length() && j < s.length()) {
String str = s.substring(i, j);
if (!str.contains(s.subSequence(j,j+1))) {
String strr = str + s.charAt(j);
if ((j - i + 1) > longestStr.length())
longestStr = strr;
j+=1;
}else {
i++;
j = i + 1;
}
}else
break;
}
// 如果字符串 s 中每一个字符都相同,则最长子串为 s.charAt(0)
if(longestStr.length() == 0 && s.length() != 0)
longestStr += s.charAt(0);
return longestStr.length();
}
- 其他方法的学习
1.暴力法
逐个检查所有的子字符串,看它是否不含有重复的字符
public int lengthOfLongestSubstring(String s) {
int n = s.length();
int ans = 0;
for (int i = 0; i < n; i++)
for(int j = i + 1; j <= n; j++)
if(allUnique(s, i, j))
ans = Math.max(ans, j-i);
return ans;
}
// 判断子字符串中字符是否唯一
public boolean allUnique(String s, int start, int end){
Set<Character> set = new HashSet<>();
for(int i = start; i < end; i++){
char ch = s.charAt(i);
if(set.contains(ch))
return false;
set.add(ch);
}
return true;
}
2.滑动窗口
如果从索引 i 到 j-1 之间的子字符串已经被检查为没有重复字符,则只需要检查索引 j 对应的字符是否已经存在于子字符串中。
用 HashSet 将字符存储在当前窗口 [i, j) 中( 最初 j=i)。然后向右侧滑动索引 j ,如果它不在 HashSet 中,继续滑动 j 。直到 j 索引处的字符已经存在于 HashSet 中。
public 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){
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;
}
}
3.优化的滑动窗口
如果 j 索引处的字符与 [i, j) 范围内 a 索引处的字符相同,我们不需要逐渐增加 i ,可以直接跳过 [i, a] 范围内的所有元素,并将 i 变为 a+1
public int lengthOfLongestSubstring(String s) {
int n = s.length(), ans = 0;
Map<Character, Integer> map = new HashMap<>();
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;
}