Given a string, find the length of the longest substring T that contains at most k distinct characters. For example, Given s = “eceba” and k = 2, T is "ece" which its length is 3.
我的做法:维护一个window,r移动到超出k distinct character限制是更新max,然后移动l使distinct character <=k; 这种做法更新max只发生在超出限制的时候,有可能永远都没有超出限制,所以while loop完了之后要补上一个max的更新
1 public class Solution { 2 public int lengthOfLongestSubstringKDistinct(String s, int k) { 3 int l=0, r=0; 4 HashMap<Character, Integer> map = new HashMap<Character, Integer>(); 5 int longest = 0; 6 if (s==null || s.length()==0 || k<=0) return longest; 7 while (r < s.length()) { 8 char cur = s.charAt(r); 9 map.put(cur, map.getOrDefault(cur, 0) + 1); 10 if (map.size() > k) { 11 longest = Math.max(longest, r-l); 12 while (map.size() > k) { 13 char rmv = s.charAt(l); 14 if (map.get(rmv) == 1) map.remove(rmv); 15 else map.put(rmv, map.get(rmv)-1); 16 l++; 17 } 18 } 19 r++; 20 } 21 longest = Math.max(longest, r-l); 22 return longest; 23 } 24 }
别人非常棒的做法:sliding window,while loop里面每次循环都会尝试更新max,所以每次更新之前都是把l, r调整到合适的位置,也就是说,一旦r移动到超出K distinct char限制,l也要更新使k distinct char重新满足,l更新是在max更新之前
1 public class Solution { 2 public int lengthOfLongestSubstringKDistinct(String s, int k) { 3 int[] count = new int[256]; 4 int num = 0, i = 0, res = 0; //num is # of distinct char, i is left edge, j is right edge 5 for (int j = 0; j < s.length(); j++) { 6 if (count[s.charAt(j)]++ == 0) num++; 7 if (num > k) { 8 while (--count[s.charAt(i++)] > 0); 9 num--; 10 } 11 res = Math.max(res, j - i + 1); 12 } 13 return res; 14 } 15 }