題目:給定一個字符串string,找出string中無重復字符的最長子串。
舉例:
Given "abcabcbb"
, the answer is "abc"
, which the length is 3.
Given "bbbbb"
, the answer is "b"
, with the length of 1.
Given "pwwkew"
, the answer is "wke"
, with the length of 3. Note that the answer must be asubstring, "pwke"
is a subsequence and not a substring.
思路:
首先,因為找的是無重復的子串,因此我們使用Hashset結構來存放已經找到的字符,HashSet中保存的是從某個位置pre到另一個位置i中間的所有字符。
從頭開始遍歷給定的字符串s, 每遍歷一個,判斷HashSet中是否有該字符,假設此時遍歷到i位置:
1: 如果沒有,就將字符加入HashSet, 表明子串的長度又增大了一個,即prev~i位置的字符串是無重復字符的,更新最長字串的長度max_str;
2: 如果有,就從prev位置開始循環遍歷,直到找到與i位置字符相等的那個字符,然后prev指向那個字符位置+1的位置,i繼續遍歷。
直到i==len結束遍歷。但此時還應該計算一次Max(i-prev, max_str)的大小,最后一次更新max_str的大小,返回最終的max_str;
擴展:
假設本題要求找出無重復的最長子串,則需要用兩個變量保存窗口的左右位置,每當max_str更新的時候,就需要更新此時的窗口左右位置。最終使用s.substring(left, right)獲取最長子串。
本題代碼:
1 public class Solution { 2 public int lengthOfLongestSubstring(String s) { 3 if(s == null || s.length() < 1) 4 return 0; 5 HashSet<Character> set = new HashSet<Character>(); 6 int pre = 0; // 窗口的左邊界 7 int max_str = Integer.MIN_VALUE; // 最長字串長度 8 int i = 0; // 窗口的右邊界 9 int len = s.length(); 10 while(i < len) 11 { 12 if(set.contains(s.charAt(i))) // 找到與i位置相等的那個字符,pre指向該字符的下一個位置,重新開始窗口 13 { 14 if(i - pre > max_str) 15 max_str = i - pre; 16 while(s.charAt(pre) != s.charAt(i)) //直到找到與當前字符相等的那個字符,然后才可以重新開始新一輪的窗口計數 17 { 18 set.remove(s.charAt(pre)); 19 pre ++; 20 } 21 pre ++; 22 } 23 else 24 { 25 set.add(s.charAt(i)); 26 } 27 i++; 28 } 29 max_str = Math.max(max_str, i - pre); // i一直向后,直到超出s的長度,此時也要計算窗口的大小 30 return max_str; 31 32 } 33 }