Question:
给定一个字符串,找出不含有重复字符的最长子串的长度。
Ex:
给定 "abcabcbb"
,没有重复字符的最长子串是 "abc"
,那么长度就是3。
给定 "bbbbb"
,最长的子串就是 "b"
,长度是1。
给定 "pwwkew"
,最长子串是 "wke"
,长度是3。请注意答案必须是一个子串,"pwke"
是 子序列 而不是子串。
Solution:对字符串中的每个字符进行遍历,得到每个字符的最长不重复子串,比较,获得整个字符串的最长无重复子串。
public class String_length {
public static 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)) //调用allUnique方法
ans = Math.max(ans, j - i);//取length最长
System.out.println(ans);
return ans;
}
//定义allUnique()使用集合将遍历得到的字符放入set中,当重复时,返回false
public static 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;
}
//主方法
public static void main(String [] args){
String aa ="aderweapturerd";
lengthOfLongestSubstring(aa);
}
}
Solution2:滑动窗口,完成对字符是否在当前的子字符串中的检查。使用 HashSet 将字符存储在当前窗口 [i,j)[i, j)[i,j)(最初 j=ij = ij=i)中。 然后我们向右侧滑动索引 jjj,如果它不在 HashSet 中,我们会继续滑动 jjj。直到 s[j] 已经存在于 HashSet 中。此时,我们找到的没有重复字符的最长子字符串将会以索引 iii 开头。如果我们对所有的 iii 这样做,就可以得到答案。
public static int lengthOfLongestSubstring(String s) {
int n = s.length();
Set<Character> set = new HashSet<>();//set集合元素无序,不重复
int ans = 0, i = 0, j = 0;
while (i < n && j < n) {
if (set.contains(s.charAt(j))){//判断集合是否存在相同字符
set.remove(s.charAt(i++));
}
else {
set.add(s.charAt(j++));//将不重复的字符存入set,j++
ans = Math.max(ans, j - i);
}
}
System.out.println(ans);
return ans;
}
优化的滑动窗口:
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;
}
2019-09-23增加获取最长字符方法:
/**
* @description 获取最长字符
* @author Lin
* @date 2019年9月23日
* @param str
*/
public static void getMaxString(String str) {
int n = str.length();
int length = 0;
List<Character> list = new ArrayList<Character>();
List<Character> maxList = new ArrayList<Character>();
List<String> strList = new ArrayList<String>();//存放最长子字符串
for (int i = 0; i < n; i++) {
char a = str.charAt(i);
if(list.contains(a)){
int index = list.indexOf(a);
//list = list.subList(index+1,list.size());//数据过大会导致栈溢出
list = new ArrayList<Character>(list.subList(index+1,list.size()));
}
list.add(a);
length = Math.max(length, list.size());
if(maxList.size()<=list.size()){//取当前最长字符串
maxList.clear();
maxList.addAll(list);
strList.add(maxList.toString());
if(strList.get(0).length()<list.size()){
strList.clear();
strList.add(list.toString());
}
}
}
System.out.println("=strList===" + strList.toString());
System.out.println("=maxList===" + maxList.toString());
System.out.println("=length===" + length);
}