動態規劃-最長不含重複字符的子字符串

題目描述

輸入一個字符串(只包含 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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章