题目
输入一个字符串(只包含a-z的字符)。求其最长不含重复字符的子字符串的长度。例如,对于arabcacfr,最长不含重复字符的子字符串为acfr,长度为4。
解题思路
(1) 动态规划,用f(i)表示以i个字符结尾不包含重复子字符串的最长长度,从左往右扫描
1.若第i个字符在之前没有出现过,则f(i)=f(i-1) + 1
2.若第i个字符在之前出现过,计算第i个字符距离上次出现之间的距离为d
(1) 若d <= f(i-1),则说明第i个字符上次出现在f(i-1)对应的不包含重复字符的字符串之内,那么这时候更新f(i)=d
(2) 若d > f(i-1),则无影响,f(i) = f(i-1) + 1
分析arabcacfr
f(0) = 1, a
f(1) = 2, ar
f(3) = 2, ra, 因为d=2, f(1) = 2, 所以上一个a在 f(1) 之中
f(3) = 3, rab
f(4) = 4, rabc
f(5) = 3, bca,因为d=3,f(1)=4,所以上一个a一定在f(4)中
f(6) = 2, ac
f(7) = 3, acf
f(8) = 4, acfr,因为d=7,f(7)=3,因此上一个r不在f(7)中,f(8) = f(7) + 1
源代码
package Arithmetic;
import java.util.Arrays;
public class LongestSubString {
public static void main(String[] args) {
System.out.println(lengthOfLongestSubString("arabc"));
}
//动态规划
private static int lengthOfLongestSubString(String str) {
int curLength = 0;//当前长度
int maxLength = 0;//最大长度
int[] position = new int[26];//保存当前字符是否出现过
Arrays.fill(position, -1);//-1表示没出现过
for (int i = 0; i < str.length(); i++) {
//这里用到a~z分别用0~25下标存,所以当一个a出现的时候,只需要计算其a-'a'这个位置的下标
//即可判断是否出现过,如果出现过,则将这个值存储下来
int prevIndex = position[str.charAt(i) - 'a'];
//字符串"arabcacfr"
//如果在之前没有出现过,或者出现过但是在前一个不重复子串的前面,比如上面的字符串,最后一个r
//因为当前的最长子串是acf,而r前一次出现还是在这个子串之前,所以还是等于子串加1
if (prevIndex < 0 || i - prevIndex > curLength) {
curLength++;
} else {//如果在之前出现过,且前面的最长不重复子串之前
if (curLength > maxLength)//因为不在重复子串之间,所以当前不重复的最长子串为两个字符之间i-prevIndex
maxLength = curLength;
curLength = i - prevIndex;
}
position[str.charAt(i) - 'a'] = i;
if (curLength > maxLength)
maxLength = curLength;
}
return maxLength;
}
}
(2) HashMap
源代码
import java.util.HashMap;
public class LongestNonRepeatingSubStr {
private static int LongestNonRepSubStr(String string) {
int maxLen = 0;//保存最长不重复子串的长度
int left = -1;
if (string == null || string.length() == 0)
return maxLen;
HashMap<Character, Integer> map = new HashMap<>();//HashMap存储字符及对应的下标
for (int i = 0; i < string.length(); i++) {
char c = string.charAt(i);
if (map.containsKey(c) && map.get(c) > left)
left = map.get(c);
map.put(c, i);
maxLen = Math.max(maxLen, i - left);
}
return maxLen;
}
public static void main(String[] args) {
System.out.println(LongestNonRepSubStr("arabcacfr"));
}
}