題目描述
輸入一個字符串(只包含 a~z 的字符),求其最長不含重複字符的子字符串的長度。例如對於 arabcacfr,最長不含重複字符的子字符串爲 acfr,長度爲 4。
Solution
使用數組記錄a~z字符上一次出現的位置preI,當字符上一次出現在當前子串時,curI-preI爲截去重複字符的子串長度。
public int longestSubStringWithoutDuplication(String str) {
int curLen = 0;
int maxLen = 0;
int[] preIndex = new int[26];
Arrays.fill(preIndex, -1);
for (int curI = 0; i < str.length(); curI++) {
int c = str.charAt(curI) - 'a';
int preI = preIndex[c];
if (preI == -1 || curI - preI > curLen) { //字符未出現或字符上一次出現位置不在當前不重複子串內
curLen++; //子串長加1
} else {
maxLen = Math.max(maxLen, curLen);
curLen = curI - preI;
}
preIndex[c] = curI;
}
maxLen = Math.max(maxLen, curLen);
return maxLen;
}
時間換空間,使用一個變量保存上一個字符結尾的最長不重複子串長度。
dp[i]遍歷以dp[i-1]結尾的最長子串每個位置,看當前字符是否包含在子串中,
如果包含 dp[i]=i - 上一個包含的字符的位置。如果不包含,dp[i]=dp[i-1]+1 。
public int longestSubStringWithoutDuplication(String str) {
int maxLen = 1;
int pre = 1; //上一位字符結尾的最長子串長
for (int curI = 1; curI < str.length(); curI++) {
int startI = curI - pre; //子串起始位置
int i;
for (int i = curI - 1; i >= startI; i--) {
if (str.charAt(curI) == str.charAt(i)) {
break;
}
}
pre = curI - i; //當前字符結尾的最長不重複子串長
maxLen = Math.max(maxLen, pre);
}
return maxLen;
}