給定一個字符串,找出不含有重複字符的 最長子串 的長度。
示例:
給定 "abcabcbb"
,沒有重複字符的最長子串是 "abc"
,那麼長度就是3。
給定 "bbbbb"
,最長的子串就是 "b"
,長度是1。
給定 "pwwkew"
,最長子串是 "wke"
,長度是3。請注意答案必須是一個子串,"pwke"
是 子序列 而不是子串。
思路:
我看見這道題目的第一感覺,就是從頭遍歷過來,將之前遍歷的一小段沒有重複字符的字符串存起來,如果出現新的字符串,就開闢一個新的字符串,進入下一不重複字符的字符串存儲。
乍一看好像思路不錯沒有什麼遺漏。但是自信想象就會發現,如果我在遇到新的字符串的時候,就要開始在容器中新建一個字符的話,最後得到的不重複字符串肯定不對。比如abad,按照我剛纔的思路會得到ab,ad兩個字符串。但是正確的答案應該得到ab,bad!所以我需要做另外的處理來解決這個問題。
我選擇的解決方案是在遍歷的過程中遇到新的字符串的時候,新建一個StringBuffer對象(因爲避免內存問題,所以選擇的StringBuffer或StringBuilder)。同時會將list中當前的StringBuffer對象取出來,截取與當前遍歷的字符相同的字符之後的所有字符,拼接到新建的StrngBuffer中。
如果就可以獲得各個沒有重複字符串的 字符串StringBuffer的list集合。之後再排序選取最長字符串的即可獲得結果。
如下是鄙人寫的代碼:
public static int lengthOfLongestSubstring(String s) {
if(s == null || s.length()==0)
return 0;
List<StringBuffer> list = new ArrayList<StringBuffer>();
list.add(new StringBuffer());
int index = 0;
for(int i = 0;i<s.length();i++){
String word = String.valueOf(s.charAt(i));
//如果不包含 則可以拼接到list中
if(!list.get(index).toString().contains(word)){
list.get(index).append(word);
}else{
//發現重複字符串,需要新增元素,並且將前面不重複的部分拷貝過來
index++;
list.add(new StringBuffer(word));
int indexOfWord = list.get(index-1).toString().indexOf(word);//前一個字符串該字出現的位置
list.get(index).insert(0,list.get(index-1).substring(indexOfWord+1,list.get(index-1).length()));
}
}
List<Integer> nums = new ArrayList<Integer>(list.size());
for(int i = 0 ; i<list.size() ; i++){
nums.add(list.get(i).toString().length());
}
Collections.sort(nums);
return nums.get(nums.size()-1);
}
下面是大神寫的代碼:
public static int lengthOfLongestSubstring2(String s) {
int[] list = new int[256]; // 初始化asc碼數的字符數值,都默認爲 -1
int previous = -1, right = 0, max_len = 0;
for(int i=0;i<list.length;i++){
list[i]=-1;
}
//進行遍歷,每往右走一個字符,right就增加一,代表着第幾個字符。
//如果出現重複的字符,那麼當前的 list[(int)c] 的值就會>-1(出現過的字符的值爲對應right值,即第幾個)
//同時precious也一直保持着最近出現的 重複字符的上此次出現的 座標
//因此,每次出現重複字符,並且重複字符的座標在previous之後的,這可以表示爲在之後出現了重複字符串,
// 同時記錄該字符串起始位置 previous = list[(int)c] (該字符串結束位置爲list[(int)c] = right++)
//Math.max(max_len, right - previous) 一直保持着最長字符串的長度
while(right<s.length()){
char c = s.charAt(right);
if(list[(int)c] > previous)
previous = list[(int)c];
max_len = Math.max(max_len, right - previous);
list[(int)c] = right++;
}
return max_len;
}
可見大神代碼多麼簡介,並且少了很多不必要的過程。
若有不足,還望指正,大家一起學習,共勉!