解决哪类问题

:::success 求解连续区间最值 :::

代码模板

求最大窗口大小(for版本)

  1. int maxLen = 0; // 窗口最大值
  2. int sum = 0; // 当前状态
  3. for(int l = 0, r = 0; r < arr.length; r++) {
  4. sum += arr[r]; // 根据加入右指针更新状态
  5. if (sum <= maxCost) { // 满足约束
  6. maxLen = Math.max(maxLen, r - l + 1); // 更新窗口最大值
  7. } else { // 不满足约束
  8. sum -= arr[l]; // 根据去除左指针更新状态
  9. l++; // 左指针右移
  10. }
  11. }
  12. return maxLen;

求最大窗口大小(双while版本1)

  1. while(r < n){
  2. UPDATE STATE(r)
  3. while(WRONG){
  4. UPDATE STATE(l)
  5. l++
  6. }
  7. MAXORMIN(ans)
  8. r++
  9. }

求最大窗口大小(双while版本2)

  1. int l = 0, r = 0, sum = 0, maxLen = 0; // 初始化左右指针,状态值,窗口大小
  2. while (r < n) { // 右指针不越界
  3. sum += arr[r]; // 根据加入右指针更新状态
  4. while(sum > maxCost) { // 不符合约束条件
  5. sum -= arr[l]; // 根据去除左指针更新状态
  6. l++; // 左指针右移
  7. }
  8. maxLen = Math.max(maxLen, r - l + 1); // 更新窗口最大值
  9. r++; // 右指针右移
  10. }
  11. return maxLen;

求最大窗口大小(双while版本3)

  1. int l = 0, r = 0, sum = 0, maxLen = 0; // 初始化左右指针,状态值,窗口大小
  2. while (r < n) { // 右指针不越界
  3. sum += arr[r]; // 根据加入右指针更新状态
  4. r++; // 右指针右移
  5. while(sum > maxCost) { // 不符合约束条件
  6. sum -= arr[l]; // 根据去除左指针更新状态
  7. l++; // 左指针右移
  8. }
  9. maxLen = Math.max(maxLen, r - l); // 更新窗口最大值(注意区别)
  10. }
  11. return maxLen;

窗口不需要减小

  1. int l = 0, r = 0, sum = 0;
  2. for(; r < n; r++) {
  3. if(sum + arr[r] > maxCost) { // 不满足约束,左右指针同时移动
  4. sum += arr[r] - arr[l]; // 更新状态
  5. l++;
  6. } else { // 满足约束,右指针移动
  7. sum += arr[r]; // 更新状态
  8. }
  9. }
  10. return r - l;

滑动窗口复杂样板

  1. public String minWindow(String s, String t) {
  2. int left = 0, right = 0; // 滑动窗口前后指针
  3. int min = Integer.MAX_VALUE; // 最小子串的长度
  4. int start = 0, end = 0; // 最小子串的左右位置
  5. int count = 0; // 相同字符的个数
  6. Map<Character, Integer> tMap = new HashMap<>(); // target串的字符计数(目标)
  7. Map<Character, Integer> sMap = new HashMap<>(); // source串的字符计数(窗口)
  8. // 初始化target串的字符计数
  9. for (int i = 0; i < t.length(); ++i) {
  10. tMap.put(t.charAt(i), tMap.getOrDefault(t.charAt(i), 0) + 1);
  11. }
  12. while (right < s.length()) {
  13. char c = s.charAt(right);
  14. // 更新窗口状态
  15. if (tMap.containsKey(c)) { // 是所求字符
  16. sMap.put(c, sMap.getOrDefault(c, 0) + 1); // 存字符进窗口
  17. if (tMap.get(c).compareTo(sMap.get(c)) == 0) { // 看是不是该字符达标
  18. count++;
  19. }
  20. }
  21. right++; // 右滑动扩大
  22. while (count == tMap.size()) {
  23. // 满足条件,更新最值
  24. if (min > right - left) {
  25. end = right;
  26. start = left;
  27. min = right - left;
  28. }
  29. char d = s.charAt(left);
  30. // 更新窗口状态
  31. if (tMap.containsKey(d)) {
  32. sMap.put(d, sMap.get(d) - 1);
  33. if (tMap.get(d) > sMap.get(d)) {
  34. count--;
  35. }
  36. }
  37. left++; //左滑动缩小
  38. }
  39. }
  40. return min == Integer.MIN_VALUE ? "" : s.substring(start, end);
  41. }

复杂度

O(n)

运用思想

例题

题目 难度 推荐指数
3. 无重复字符的最长子串 中等 🤩🤩🤩🤩🤩
30. 串联所有单词的子串 困难 🤩🤩
187. 重复的DNA序列 中等 🤩🤩🤩🤩
219. 存在重复元素 II 简单 🤩🤩🤩🤩
220. 存在重复元素 III 中等 🤩🤩🤩
396. 旋转函数 中等 🤩🤩🤩🤩🤩
424. 替换后的最长重复字符 中等 🤩🤩🤩🤩
438. 找到字符串中所有字母异位词 中等 🤩🤩🤩🤩
480. 滑动窗口中位数 困难 🤩🤩🤩🤩
567. 字符串的排列 中等 🤩🤩🤩
594. 最长和谐子序列 简单 🤩🤩🤩🤩
643. 子数组最大平均数 I 简单 🤩🤩🤩🤩🤩
992. K 个不同整数的子数组 困难 🤩🤩🤩🤩
1004. 最大连续1的个数 III 中等 🤩🤩🤩
1052. 爱生气的书店老板 中等 🤩🤩🤩
1208. 尽可能使字符串相等 中等 🤩🤩🤩
1423. 可获得的最大点数 中等 🤩🤩🤩🤩
1438. 绝对差不超过限制的最长连续子数组 中等 🤩🤩🤩
1610. 可见点的最大数目 困难 🤩🤩🤩🤩
1838. 最高频元素的频数 中等 🤩🤩🤩
1984. 学生分数的最小差值 简单 🤩🤩🤩🤩🤩
2024. 考试的最大困扰度 中等 🤩🤩🤩🤩