劍指Offer48:最長不含重複字符的子字符串

題目:

請從字符串中找出一個最長的不包含重複字符的子字符串,計算該最長子字符串的長度

假設字符串中只包含'a'~'z'的字符

例如,在字符串“arabcacfr”中,最長的不含重複字符的子字符串是“acfr”,長度爲4

思路:

我們從頭遍歷,考慮每次所讀的當前字符爲結尾的字符串的不含重複字符的最長子字符串問題。

如我們讀到了第i個字符,假設當前以i爲結尾的字符串的最長不含重複字符的字符串長爲x,下一個字符i+1,會有兩種情況:

1)i+1字符第一次出現,則以i+1爲結尾的最長字符串長度直接爲x+1;

2)i+1字符出現過,分爲:

a、在i+1上一次出現的位置,在最長子字符串中,則此i+1字符不能添加在子字符串後。

b、在i+1上一次出現的位置,不在最長子字符串中,則i+1字符可添加,長度x+1。

代碼:

//動態規劃
public class Main {
	public static void main(String[] args) {
		String s = "arabcacfr";
		System.out.println(getLenStr(s));	
	}
	
	public static String getLenStr(String s) {
		// max用於保存位置和長度
		int maxloc = 0;
		int maxlength = 1;
		// len用於保存此字符之前字符的最長字符串長度
		int len = maxlength;
		// 用長度爲26的數組來保存字符上次出現的位置
		int[] arr = new int[26];
		// 循環 
		// 計算以每一個位置爲結尾的最長字符串長度
		for(int i=1;i<s.length();i++) {
			// 之前沒出現過 
			// 不能直接用 lastC[s.charAt(i)]==0 因爲最開始都是0  
			if(s.charAt(arr[s.charAt(i)-'a']) != s.charAt(i)) {
				len = len + 1;
			}
			
			// 之前出現過 則計算距離
			// 在上一次的最長字符串長度之外,則不影響此次的添加字符,len直接加一
			// 在上一次的最長字符串長度之內,則以此字符串結尾的最長字符只能從上一次的出現之後開始計算,即distance
			else if(s.charAt(arr[s.charAt(i)-'a'])== s.charAt(i)) {
				int dis = i - arr[s.charAt(i)-'a'];
				if(dis>len) {
					len = len +1;
				}else {
					len = dis;
				}
			}
			
			// 更新此字符串的出現位置
			arr[s.charAt(i)-'a'] = i;
			if(maxlength < len) {
				maxloc = i;
				maxlength = len;
			}
		}
		return s.substring(maxloc-maxlength+1,maxloc+1);
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章