滑动窗口(同向双指针)
了解滑动窗口
滑动窗口的原理是双指针同向移动,滑动窗口本质是在数组 / 字符串上维护一个动态变化的连续区间(可看作一个 “窗口”),通过调整窗口的左、右边界,在一次遍历中完成对目标的查找或计算。
注意左右边界移动时产生的变化
904. 水果成篮
解题思路:
将该题目理解成在数组中寻找包含两个元素的最长子数组,利用HashMap该数据结构来存储各种类型的水果也就是不同的数组元素,定义left为左指针right为右指针,右指针向右滑动的过程中HashMap存储元素种类在增加,当size()>2时停止滑动,left左指针开始向右同向滑动,当窗口中的元素种类小于2时停止。
class Solution {public int totalFruit(int[] fruits) {int len=0;//符合条件的最大数目HashMap<Integer,Integer>hashMap=new HashMap<>();int left=0,right=0;int n=fruits.length;while (right<n){hashMap.put(fruits[right],hashMap.getOrDefault(fruits[right],0)+1);while (hashMap.size()>2){//种类不符合条件,左窗口开始滑动hashMap.put(fruits[left],hashMap.get(fruits[left])-1);if (hashMap.get(fruits[left])==0)hashMap.remove(fruits[left]);//到底临界值循环即将结束(左窗口停止滑动)left++;}len=Math.max(right-left+1,len);right++;}return len;}
}
LCR 017. 最小覆盖子串
解题思路:
将子串t存入hashMap2中利用双指针left,right在字符串且存入hashMap1中,当hashMap2中元素种类和数量包含hashMap2时完成覆盖(子串覆盖目标字符串t)
class Solution {public String minWindow(String s, String t) {int len=Integer.MAX_VALUE;//记入符合条件的最短子串长度int left=0,right=0;HashMap<Character,Integer>hashMap1=new HashMap<>();HashMap<Character,Integer>hashMap2=new HashMap<>();for(int i=0;i<t.length();i++){hashMap2.put(t.charAt(i),hashMap2.getOrDefault(t.charAt(i),0)+1);}int n=s.length();int begin=-1;//记录符合条件的子串初始位置int count=0;while (right<n){hashMap1.put(s.charAt(right),hashMap1.getOrDefault(s.charAt(right),0)+1);if(hashMap1.get(s.charAt(right)).equals(hashMap2.getOrDefault(s.charAt(right),0)))count++;while (count==hashMap2.size()){//右指针停止,左指针开始移动hashMap1.put(s.charAt(left),hashMap1.getOrDefault(s.charAt(left),0)-1); if (hashMap2.containsKey(s.charAt(left))){if(hashMap1.get(s.charAt(left))<hashMap2.get(s.charAt(left)))count--;}if(right-left+1<len){begin=left;len=right-left+1;}left++;}right++;}if(begin == -1) return new String();else return s.substring(begin, begin + len);}
}
