题目描述:找出其中不含有重复字符的最长子串的长度
1.暴力破解
①从第一个字符开始,遍历到最后一个字符。
②如果有重复的字符出现,记录此时无重复的长度,跳出第一次的遍历,从第二个字符开始遍历,同样如果有重复字符出现,记录无重复的长度,循环继续。。。
③比较所有无重复的长度,选出最长的数值。
//时间复杂度O(n*n),算法最劣
public int norepeatstr1(String str){
//判断输入是否合法
if (str== null || str.length() == 0){
return 0;
}
int max = 0;//记录无重复子串的最大长度
for(int i = 0; i< str.length(); i++){
HashSet<Character> hashset = new HashSet<Character>();
for (int j = i; j < str.length(); j++){
//如果hashset中含有字符str.charAt(j),则跳出循环,
//重新从下一个字符开始计算最大无重复长度
if(hashset.contains(str.charAt(j))){
break;
}else{
//如果hashset中不含该字符,则继续添加,并记录最大长度
hashset.add(str.charAt(j));
max = Math.max(hashset.size(), max);
}
}
}
return max;
}
2.滑动窗口
①初始滑动窗口左右边界[0,0];
②右边界开始移动,将右边界经过的字符和下标用map保存下来;
③如果遇到重复字符,获取左边界的下标;
④如果没有遇到重复字符,更新最大无重复子串长度;
public int norepeatstr2(String str){
//判断输入是否合法
if (str== null || str.length() == 0){
return 0;
}
int max = 0;//记录最大值
int left = 0, right = 0;//滑动窗口的左边界和右边界
HashMap<Character, Integer> hashMap = new HashMap<>();
for (; right < str.length(); right++){
if(hashMap.containsKey(str.charAt(right))){
left = Math.max(hashMap.get(str.charAt(right)), left);
}
//map存储右边界滑过的字符和该字符的下标+1
hashMap.put(str.charAt(right), right+1);
//更新无重复子串的最大长度
max = Math.max(max, right-left+1);
}
return max;
}
拓展:不含有重复字符的最长子串(返回字符串,而不是长度)
①利用滑动窗口法计算最长子串;
②在计算最长子串时利用rightidx记录最长子串时的右边界;
③根据长度max和右边界rightidx可得到最长子串。
public String norepeatstr3(String str){
//判断输入是否合法
if (str == null || str.length() == 0)
return "";
HashMap<Character,Integer> hashmap = new HashMap();
int left = 0, right = 0;//窗口的左右边界
int max = 0, rightidx = 0;
for (;right<str.length();right++){
//如果窗口内存在重复元素
if(hashmap.containsKey(str.charAt(right))){
left = Math.max(left, hashmap.get(str.charAt(right)));
}
hashmap.put(str.charAt(right),right+1);
//rightidx用来记录无重复子串最大值时的右边界
rightidx = max>(right-left+1)?rightidx:right;
max = Math.max(max, right-left+1);
}
//窗口内的字符串即为最长子串
char[] arr = str.toCharArray();
//rightidx-max+1为左边界
return new String(arr,rightidx-max+1,max);
}