無重複字元的最長子串(佇列,滑動視窗)
阿新 • • 發佈:2018-11-03
給定一個字串,找出不含有重複字元的最長子串的長度。
示例 1:
輸入: "abcabcbb"
輸出: 3
解釋: 無重複字元的最長子串是 "abc",其長度為 3。
示例 2:
輸入: "bbbbb"
輸出: 1
解釋: 無重複字元的最長子串是 "b",其長度為 1。
示例 3:
輸入: "pwwkew"
輸出: 3
解釋: 無重複字元的最長子串是 "wke",其長度為 3。
請注意,答案必須是一個子串,"pwke" 是一個子序列 而不是子串。
思路:給定一個佇列,新增計數,檢測是否有重複的key,重複則出列,直到key出列,然後key進佇列計算count=size
若無重複則count++
class Solution { public int lengthOfLongestSubstring(String s) { if (s.equals("")) { return 0; } int count = 1; int max=1; Queue<Character> list = new LinkedList<Character>(); list.offer(s.charAt(0)); for (int i = 1; i < s.length(); i++) { if (list.contains(s.charAt(i))) { do { list.poll(); } while (list.contains(s.charAt(i))); list.offer(s.charAt(i)); count = list.size(); } else { ++count; list.offer(s.charAt(i)); } if (max < count) { max = count; } } return max; }}
其中佇列可以替換為為hashset,同理.,兩個指標,一個表示當前,一個表示刪除指標,刪除一直進行到不包含當前char為止
class Solution { public 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) { // try to extend the range [i, j] if (!set.contains(s.charAt(j))){ set.add(s.charAt(j++)); ans = Math.max(ans, j - i); } else { set.remove(s.charAt(i++)); } } return ans; }}
還可以繼續優化,這裡時間複雜度為2n
可以繼續優化為n,使用map,key為char,value記錄當前char的下標,當發現重複的時候 j 直接跳到
Max(重複的地方+1 ,j)//防止abcba 出現 j變小的現象 ,j只會線性增加
class Solution {
public int lengthOfLongestSubstring(String s) {
HashMap<Character,Integer> map = new HashMap<>();
int j=0,ans=0;
for(int i=0;i<s.length();i++){
if(map.containsKey(s.charAt(i))){
j =Math.max(map.get(s.charAt(i))+1,j) ;
}
ans = Math.max(ans,i-j+1);
map.put(s.charAt(i),i);
}
return ans;
}}
這裡map可以還可以優化為陣列 int[] a = new int[];
int [26]
用於字母 ‘a’ - ‘z’或 ‘A’ - ‘Z’int [128]
用於ASCII碼int [256]
用於擴充套件ASCII碼- index[s.charAt(i)] = i;