思路:最简单的就是暴力法了。直接枚举所有的字串,筛选出非重复子串,然后再筛选出最大字串。返回长度。
public class Solution {
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++) {
Character ch = s.charAt(i);
if (set.contains(ch)) return false;
set.add(ch);
}
return true;
}
作者:LeetCode
链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/solution/wu-zhong-fu-zi-fu-de-zui-chang-zi-chuan-by-leetcod/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
思路2:定义一个滑动窗口,left right 代表窗口的左沿和右沿,这个滑动窗口内部保存的是不含重复字符的字串。
首先,left 和right的移动,每当right 向后移动时,记录下来当前的字符,我们使用HashSet进行存储,这样就可以去重。每当我们扫描到重复的字符时,做窗口就向后移动。
举个例子:
循环往复,每一次right向后移动时,都要计算当前的最大长度,并且保存。
public int lengthOfLongestSubstring(String s) {
//保存已存在的字符
HashSet set = new HashSet();
//结果
int ans = 0;
//窗口的左右沿
int left = 0;
int right = 0;
//字符串长度
int n = s.length();
while(left < n && right < n){
//假如不存在此字符,那么就说明 left -》right 这个窗口内部没有这个字符
//所以直接在窗口的右沿向后移动
if(!set.contains(s.charAt(right))){
//把当前字符存入HashSet中
set.add(s.charAt(right));
//右沿向后移动
right++;
//记录当前窗口的最大值
ans = ans > (right-left) ? ans: right-left;
}else{
// 如果存在,那么就直接窗口向后移动,
// aba 此时窗口移动为 ba 如果为 bb 移动为 b
set.remove(s.charAt(left++));
}
}
return ans;
}
思路三优化滑动窗口算法
使用HashMap 存储字符以及对应的索引位置。当我们扫描到重复字符时就饿可以直接定位到之前的重复字符的位置,那么我们直接将窗口左沿移动到他的后面就可以了。
直到 right 到末尾结束,同样每次保存最长字符串的长度。
public int lengthOfLongestSubstring(String s){
// 使用HashMap记录 字符 与索引的映射
HashMap<Character,Integer> map = new HashMap();
//记录结果
int ans = 0;
//字符长度
int len = s.length();
//滑动窗口的左右沿
int left = 0;
int right = 0;
while(right < len){
//如果此字符已经存在,那么就要更新left的值,也就是窗口左沿
//使得窗口直接到对应的重复字符的位置的下一个位置,
if(map.containsKey(s.charAt(right))){
//对比一下当前的左沿的位置 和 重复字符的位置谁大,谁大用哪个
// a b c d a c d a
left = map.get(s.charAt(right)) +1 > left ? map.get(s.charAt(right)) +1 : left;
}
//不论如何都需要去将此节点去更新值
map.put(s.charAt(right),right);
ans = ans > right - left+ 1 ? ans: right -left+1;
right++;
}
return ans;
}