滑动窗口算法可以应用在很多查找字符串子串的算法中。
参考:Sliding Window algorithm template to solve all the Leetcode substring search problem.
算法1: 基本滑动窗口算法
使用HashMap存储target字符串中字符出现的次数,适用范围最广。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 public List<Integer> slidingWindowTemplate (String s, String t) { List<Integer> result = new LinkedList<>(); if (t.length()> s.length()) return result; Map<Character, Integer> map = new HashMap<>(); for (char c : t.toCharArray()){ map.put(c, map.getOrDefault(c, 0 ) + 1 ); } int counter = map.size(); int begin = 0 , end = 0 ; while (end < s.length()){ char c = s.charAt(end); if ( map.containsKey(c) ){ map.put(c, map.get(c)-1 ); if (map.get(c) == 0 ) counter--; } end++; while (counter == 0 ){ char tempc = s.charAt(begin); if (map.containsKey(tempc)){ map.put(tempc, map.get(tempc) + 1 ); if (map.get(tempc) > 0 ) counter++; } begin++; } } return result; }
如果一直target中字符的取值范围,如target中只包含大写字母、小写字母或数字,则该算法可以进一步优化,主要的优化点就是将HashMap换成数组,对数组的操作要比对HashMap的entry操作快很多。
算法2: 使用数组作为map的滑动窗口算法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public List<Integer> findAnagrams (String s, String p) { List<Integer> res = new ArrayList<>(); int [] map = new int [256 ]; for (char c : p.toCharArray()) map[c]++; int count = p.length(); int start = 0 ; for (int end = 0 ; end < s.length(); end++) { if (map[s.charAt(end)]-- > 0 ){ count--; } while (count == 0 ) { if (++map[s.charAt(start)] > 0 ) count++; start++; } } return res; }