当前位置:   article > 正文

解题技巧之滑动窗口-Java实现_java实现滑动窗口计数

java实现滑动窗口计数

滑动窗口技巧作为双指针技巧之一, 通常用于解决子字符串的匹配问题

解决这类问题的通用框架如下:

  1. /*
  2. 通用框架:
  3. 创建两个HashMap, 一个用来存储满足条件所需的key的个数(need), 另一个用来做window
  4. 遍历存need里面
  5. 创建窗口的左右指针和计数器(记录窗口中key的个数是否满足条件)
  6. 开始右指针移动,扩大窗口并增加key(窗口内一系列更新)
  7. 在while里判断左指针是否要收缩,然后进行窗口内更新(减少map)
  8. */

按照这个框架来解决第一个问题:

  1. class Solution {
  2. public String minWindow(String s, String t) {
  3. // 用一个哈希表needs计算需要的字符及出现次数,另一个window作为滑动窗口记录
  4. int start = 0;
  5. int minLength = Integer.MAX_VALUE;
  6. Map<Character, Integer> needs = new HashMap<>();
  7. Map<Character, Integer> window = new HashMap<>();
  8. // 填needs
  9. for(int i = 0; i < t.length(); i++){
  10. needs.put(t.charAt(i), needs.getOrDefault(t.charAt(i), 0) + 1);
  11. }
  12. int left = 0;
  13. int right = 0;
  14. int match = 0; // 记录window中有多少个字符符合要求
  15. while(right < s.length()){
  16. char c1 = s.charAt(right);
  17. //如果needs有对应的键,就把这个放进window
  18. if(needs.containsKey(c1)){
  19. window.put(c1, window.getOrDefault(c1, 0) + 1);
  20. if(needs.get(c1).equals(window.get(c1))){
  21. match++;
  22. }
  23. }
  24. right++;
  25. //window中的字符符合要求,调整left,更新结果
  26. while(match == needs.size()){
  27. if(right - left < minLength){
  28. start = left;
  29. minLength = right - left;
  30. }
  31. char c2 = s.charAt(left);
  32. left++;
  33. if(needs.containsKey(c2)){
  34. if(window.get(c2).equals(needs.get(c2)))
  35. match--;
  36. window.put(c2, window.getOrDefault(c2, 0) - 1);
  37. }
  38. }
  39. }
  40. return minLength == Integer.MAX_VALUE? "":s.substring(start, start+minLength);
  41. }
  42. }

与之相类似的题目还有

代码如下

  1. class Solution {
  2. public List<Integer> findAnagrams(String s, String p) {
  3. // 创建hashmap记录need和window
  4. Map<Character, Integer> need = new HashMap<>();
  5. Map<Character, Integer> window = new HashMap<>();
  6. //记录索引
  7. List<Integer> res = new ArrayList<>();
  8. // valid 记录满足条件的字符个数
  9. int valid = 0;
  10. int right = 0;
  11. int left = 0;
  12. //将p放到need里面
  13. for(int i = 0; i < p.length(); i++){
  14. need.put(p.charAt(i), need.getOrDefault(p.charAt(i), 0) + 1);
  15. }
  16. //扩大窗口,记录char并移动right
  17. while(right < s.length()){
  18. char c1 = s.charAt(right);
  19. right++;
  20. //如果存在need中的char,添加到window
  21. if(need.containsKey(c1)){
  22. window.put(c1, window.getOrDefault(c1, 0) + 1);
  23. if(need.get(c1).equals(window.get(c1))){
  24. valid++;
  25. }
  26. }
  27. //判断left是否++
  28. while(right - left >= p.length()){
  29. if(valid == need.size()){
  30. res.add(left);
  31. }
  32. char c2 = s.charAt(left);
  33. left++;
  34. if(need.containsKey(c2))
  35. if(need.get(c2).equals(window.get(c2)))
  36. valid--;
  37. window.put(c2, window.getOrDefault(c2, 0) - 1);
  38. }
  39. }
  40. return res;
  41. }
  42. }

其他类似的题目可以参考东哥的,不过实现方式都是C++

https://github.com/labuladong/fucking-algorithm/blob/master/算法思维系列/滑动窗口技巧进阶.md

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/274669
推荐阅读
相关标签
  

闽ICP备14008679号