【Java】 劍指offer(48) 最長不含重複字符的子字符串

本文參考自《劍指offer》一書,代碼採用Java語言。html

更多:《劍指Offer》Java實現合集  java

題目 

  請從字符串中找出一個最長的不包含重複字符的子字符串,計算該最長子字符串的長度。假設字符串中只包含從'a'到'z'的字符。數組

思路

  動態規劃法:定義函數f(i)爲:以第i個字符爲結尾的不含重複字符的子字符串的最大長度。函數

  (1)當第i個字符以前未出現過,則有:f(i)=f(i-1)+1post

  (2)當第i個字符以前出現過,記該字符與上次出現的位置距離爲d測試

    1)若是d<=f(i-1),則有f(i)=d;url

    2)若是d>f(i-1),則有f(i)=f(i-1)+1;htm

  咱們從第一個字符開始遍歷,定義兩個int變量preLength和curLength來分別表明f(i-1)和f(i),再建立一個長度爲26的pos數組來存放26個字母上次出現的位置,便可根據上述說明進行求解。blog

  注意:每次最大長度和字母出現位置要記得更新。字符串

  另外一種思路:遍歷每一個字符,把當前字符當作子字符串的末尾結點,同時更新開頭結點,詳細代碼見Longest Substring Without Repeating Characters

測試算例 

  1.功能測試(一個或者多個字符,所有字符不一樣/相同)

  2.特殊測試(null,空字符串)

Java代碼

//題目:請從字符串中找出一個最長的不包含重複字符的子字符串,計算該最長子
//字符串的長度。假設字符串中只包含從'a'到'z'的字符。

public class LongestSubstringWithoutDup {
	public static int  maxLength(String str) {
		if(str==null || str.length()<=0)
			return 0;
		int preLength=0;  //即f(i-1)
		int curLength=0;  //即f(i)
		int maxLength=0;
		int[] pos= new int[26];  //用於存放字母上次出現的位置
		for(int i=0;i<pos.length;i++)
			pos[i]=-1;
		for(int i=0;i<str.length();i++) {
			int letterNumber = str.charAt(i)-'a';
			if(pos[letterNumber]<0 || i-pos[letterNumber]>preLength) {
				curLength=preLength+1;
			}else {
				curLength=i-pos[letterNumber];
			}
			pos[letterNumber]=i;
			if(curLength>maxLength)
				maxLength=curLength;			
			preLength=curLength;
		}
		return maxLength;
	}
	
	public static void main(String[] args) {
		System.out.println(maxLength("arabcacfr")==4);
		System.out.println(maxLength("a")==1);
		System.out.println(maxLength("aaa")==1);
		System.out.println(maxLength("abcdef")==6);
		System.out.println(maxLength("")==0);
		System.out.println(maxLength(null)==0);
	}
}

  

收穫

  1.函數f(i)爲:以第i個字符爲結尾的不含重複字符的子字符串的最大長度。而不是以第i個字符做爲開頭。第i個字符做爲結尾能夠方便與下一個字符進行聯繫。

  2.學會用長度爲26的數組來存放26個字母所在的位置下標。

 

更多:《劍指Offer》Java實現合集 

相關文章
相關標籤/搜索