leetcode刷題之無重複的最長子串
阿新 • • 發佈:2018-12-27
題目要求:
給定一個字串,找出不含有重複字元的 最長子串 的長度。
示例:
給定 "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; }
可見大神程式碼多麼簡介,並且少了很多不必要的過程。
若有不足,還望指正,大家一起學習,共勉!