本文參考自《劍指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,空字符串)
//題目:請從字符串中找出一個最長的不包含重複字符的子字符串,計算該最長子 //字符串的長度。假設字符串中只包含從'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個字母所在的位置下標。