题目
输入一个字符串(只包含 a~z 的字符),求其最长不含重复字符的子字符串的长度。例如对于 arabcacfr,最长不含重复字符的子字符串为 acfr,长度为 4。
思路
方法1
- 动态规划,dp[i] 表示 以第i个字符结尾的串,最长不含重复字符的子串长度。
- 第i个字符未出现过,dp[i] = dp[i - 1] + 1,
- 第i个字符出现过,该字符与上次出现的位置距离为d:
- 如果d <= dp[i - 1],dp[i] = d;
- 如果d > dp[i - 1],dp[i] = dp[i - 1] + 1;
public int LongestSubstringWithoutDuplication (String str) {
// 每个字符上次出现的位置
int[] preIndex = new int[26];
for (int i = 0; i < 26; i++) {
preIndex[i] = -1;
}
int curLength = 0;
int maxLength = 0;
for (int i = 0; i < str.length(); i++) {
int c = str.charAt(i) - 'a';
if (preIndex[c] == -1 || i - preIndex[c] > curLength) {
curLength++;
} else {
maxLength = Math.max(maxLength, curLength);
curLength = i - preIndex[c];
}
preIndex[c] = i;
}
maxLength = Math.max(maxLength, curLength);
return maxLength;
}
方法2
- 遍历每个字符,把当前字符看成子字符串的末尾结点,同时更新开头结点。
public int LongestSubstringWithoutDuplication (String str) {
int[] preIndex = new int[26];
for (int i = 0; i < 26; i++) {
preIndex[i] = -1;
}
int startIndex = 0;
int maxLength = 0;
for (int i = 0; i < str.length(); i++) {
int c = str.charAt(i) - 'a';
if (preIndex[c] >= startIndex) {
startIndex = preIndex[c] + 1;
}
maxLength = Math.max(i - startIndex + 1, maxLength);
preIndex[c] = i;
}
return mexLength;
}