滑动窗口
最小覆盖子串
class Solution { public String minWindow(String s, String t) { int[] a = new int[128]; for (char ch : t.toCharArray()) { a[ch]++; } int[] b = new int[128]; int left = 0, right = 0, l = 0, min = s.length() + 1; char[] arr = s.toCharArray(); int dis = 0; //窗口内与t相同的数量 for (int i = 0; i < arr.length; i++) { if (a[arr[i]] > 0) { b[arr[i]]++; if (b[arr[i]] <= a[arr[i]]) { //如果大于就不算进去了。因为大于也满足。 dis++; } } if (dis == t.length()) { //左指针移动条件:arr[l]不在t内或者arr[l]在窗口内部的数量大于t中arr[l]的数量 while (a[arr[l]] == 0 || b[arr[l]] > a[arr[l]]) { if (a[arr[l]] > 0) { b[arr[l]]--; } l++; } if (i - l + 1 < min) { left = l; right = i; min = i - l + 1; } } } return min == s.length() + 1 ? "" : s.substring(left, right + 1); } }
长度最小的子数组
class Solution { public int minSubArrayLen(int s, int[] nums) { int sum = 0, l = 0, min = nums.length + 1; for (int i = 0; i < nums.length; i++) { sum += nums[i]; //窗口滑动的条件是找到使得sum > s 的最大 l while (sum > s) { if (sum - nums[l] < s) break; sum -= nums[l]; l++; } if (sum >= s && i - l + 1 < min) { min = i - l + 1; } } return min == nums.length + 1 ? 0 : min; } }
替换后的最长重复字符
class Solution { public int characterReplacement(String s, int k) { if (k + 1 > s.length()) return s.length(); int[] a = new int[26]; int l = 0, max = k + 1; char[] cs = s.toCharArray(); for (int i = 0; i < cs.length; i++) { a[cs[i]-'A']++; //l 移动的条件是当前窗口里面的数量最多的那个数字+k也不能填满窗口 while (l <= i && max(a) + k < i - l + 1) { a[cs[l] - 'A']--; l++; } max = Math.max(max, i - l + 1); } return max; } private int max(int[] A) { int max = 0; for (int i = 0; i < 26; i++) { max = Math.max(max, A[i]); } return max; } }
其实可以优化一下
class Solution { public int characterReplacement(String s, int k) { int dis = 0, l = 0, res = 0; int[] a = new int[26]; char[] cs = s.toCharArray(); for (int i = 0; i < cs.length; i++) { a[cs[i] - 'A']++; //因为当窗口缩短时,不会出现窗口内相同元素的数量大于dis的情况 dis = Math.max(a[cs[i] - 'A'], dis); while (dis + k < i - l + 1) { a[cs[l] - 'A']--; l++; } res = Math.max(res, i - l + 1); } return res; } }
找到字符串中所有字母异位词
窗口固定
class Solution { public List<Integer> findAnagrams(String s, String p) { int[] a = new int[26]; int[] b = new int[26]; List<Integer> list = new ArrayList<>(); for (char ch : p.toCharArray()) { a[ch-'a']++; } char[] arr = s.toCharArray(); int n = p.length(); for (int i = 0; i < arr.length; i++) { b[arr[i]-'a']++; if (i - n >= 0) { b[arr[i - n]-'a']--; } boolean mark = true; for (int j = 0; j < 26; j++) { if (a[j] != b[j]) { mark = false; break; } } if (mark) list.add(i - n + 1); } return list; } }
窗口不固定
class Solution { public List<Integer> findAnagrams(String s, String p) { List<Integer> res = new ArrayList<>(); int[] a = new int[26]; for (char ch : p.toCharArray()) { a[ch - 'a']++; } int l = 0; int[] b = new int[26]; char[] cs = s.toCharArray(); for (int i = 0; i < cs.length; i++) { b[cs[i] - 'a']++; //左指针移动的条件是如下,每次i++就进行如下判断,就可以放心地移动左指针了。 while (b[cs[i] - 'a'] > a[cs[i] - 'a']) { b[cs[l] - 'a']--; l++; } if (i - l + 1 == p.length()) { res.add(l); } } return res; } }
字符串的排列
这个题和上面写法一模一样
class Solution { public boolean checkInclusion(String s1, String s2) { int[] a = new int[26]; for (char ch : s1.toCharArray()) { a[ch - 'a']++; } int[] b = new int[26]; int l = 0; char[] cs = s2.toCharArray(); for (int i = 0; i < cs.length; i++) { b[cs[i] - 'a']++; while (b[cs[i] - 'a'] > a[cs[i] - 'a']) { b[cs[l] - 'a']--; l++; } if (i - l + 1 == s1.length()) { return true; } } return false; } }

浙公网安备 33010602011771号