LeetCode 3. 無重複字元的最長子串(Java版)
阿新 • • 發佈:2019-01-07
方法一
窮舉所有的子串(定義兩個函式):
①第一個函式窮舉所有可能出現的子串結果,對於字串的每一個字元,它所構成的子串是下標比它大的所有子串組合
eg:abc
對於a,子串有a, ab,abc,
對於b,子串有b,bc,
對於c,有子串c
所以字串abc的所有的子串為a,ab,abc,b,bc,c
②第二個函式使用者過濾窮舉出來的子串是否重複,用hashset
時間複雜度o(n^3)這種方法會超時
class Solution { public int lengthOfLongestSubstring(String s) { int res=0; for(int i=0;i<s.length();i++){ for(int j=i+1;j<=s.length();j++){ if(isTrue(s,i,j)) res=Math.max(res,j-i); } } return res; } public boolean isTrue(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; } }
方法二
滑動視窗法:
定義兩個指標,start和end,代表當前視窗的開始和結束位置,同樣使用hashset,當視窗中出現重複的字元時,start++,沒有重複時,end++,每次更新長度的最大值
時間複雜度o(n)
public class Solution { public int lengthOfLongestSubstring(String s) { int n = s.length(); int res = 0; int end=0,start=0; Set<Character> set=new HashSet<>(); while(start<n && end<n){ if(set.contains(s.charAt(end))){ set.remove(s.charAt(start++)); }else{ set.add(s.charAt(end++)); res=Math.max(res,end-start); } } return res; } }
方法三
由方法二得到的滑動視窗,每次在[start,end]中如果有重複的,我們的做法是更新視窗從end重新開始,這種方法要求定義一個hashmap儲存字元到索引的對映,並且每次都會更新map的值
時間複雜度o(n)
public class Solution { public int lengthOfLongestSubstring(String s) { int n = s.length(); int res = 0; int end=0,start=0; Map<Character,Integer> map=new HashMap<>(); for(;start<n && end<n;end++){ if(map.containsKey(s.charAt(end))){ start=Math.max(map.get(s.charAt(end)),start);//從有重複的下一個位置繼續找 } map.put(s.charAt(end),end+1);//map每次更新 res=Math.max(res,end-start+1);//結果每次更新 } return res; } } /* eg abca start end res map 滑動視窗範圍 0 0 1 a->1 a 0 1 2 a->1,b->2 a,b 0 2 3 a->1,b->2,c->3 a,b,c 1 3 3 a->4,b->2,c->3 b,c,a */