給定一個字符串,請你找出其中不含有重複字符的 最長子串 的長度。
示例 1:
輸入: "abcabcbb"
輸出: 3
解釋: 因爲無重複字符的最長子串是 "abc",所以其長度爲 3。
思路1:使用雙層for循環判斷每次字串是否含有重複元素,然後不重複,用兩個指針的位置i,j相減得到長度與之前長度比較取大值。時間複雜度O(n*3)
public class Num3 {
public static void main(String[] args) {
String s="badadke";
System.out.println(lengthOfLongestSubstring(s));
int num=0;
for (int i = 0; i < s.length()-1 ; i++) {
for (int j = i+1; j <= s.length(); j++) {
if(isUnique(s,i,j)){
num= Math.max(num,j-i);
}
}
}
System.out.println(num);
}
public static Boolean isUnique(String s,int start,int end) {
Set<Character> set = new HashSet<>();
for (int i = start; i < end ; i++) {
if(set.contains(s.charAt(i))){
return false;
}
set.add(s.charAt(i));
}
return true;
}
}
思路2:再思路一的基礎上優化,循環花費了太多的時間。判斷是否重複使用set集合,如果包含了該元素,從頭指針位置開始移動直到移除掉碰見的重複元素。兩個指針i,j。字串不重複的時候,j一直++。遇到重複的元素時。set remove(i++),直到不包含位置j的元素。同樣比較大小j-i與之前長度比較取最大。
public static int lengthOfLongestSubstring(String s) {
int n = s.length();
Set<Character> set = new HashSet<>();
int ans = 0, i = 0, j = 0;
while (i < n && j < n) {
if (!set.contains(s.charAt(j))){ //不重複字串繼續擴展
set.add(s.charAt(j++));
ans = Math.max(ans, j - i); /計算最大不重複字串長度
}
else {
set.remove(s.charAt(i++)); //移除之前的重複元素直到移除與當前j元素重複的位置。
}
}
return ans;
}
思路3: 再思路1的基礎上再優化,不需要從字串中把之前的重複元素都移除掉。直接找到字串中重複元素的位置,然後從該位置的下一個位置開始重新計算新的字串長度,比較長度取最大。
public static int lengthOfLongestSubstring(String s) {
int n = s.length(), ans = 0;
Map<Character, Integer> map = new HashMap<>();
for (int j = 0, i = 0; j < n; j++) {
if (map.containsKey(s.charAt(j))) {
i = Math.max(map.get(s.charAt(j)), i); //找到字串中重複元素位置
}
ans = Math.max(ans, j - i + 1);
map.put(s.charAt(j), j + 1);
}
return ans;
}