滑动窗口是双指针的一种应用,形象点说就是维护一个窗口,在窗口滑动的过程中进行窗口内数据的更新,并判断是否符合答案。初始时两个指针均指向开头,然后右指针依次向右滑动,在滑动的过程中需要收缩的时候进行左指针的移动,当右指针移出的时候结束循环即可。
滑动窗口法常用于求解满足某种条件的某段连续区间的最短或最长子序列(一般为子数组、子字符串等),如:
1)最小摘要
2)和大于给定目标值的最短子序列
3)无重复字符的最长子串
4)有k个不同字符的子串
滑动窗口的重要性质是:窗口的左边界和右边界永远只能向右移动,而不能向左移动。这是为了保证滑动窗口的时间复杂度是 O(n)。如果左右边界向左移动的话,这叫做“回溯”,算法的时间复杂度就可能不止 O(n)
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
输入:target = 7, nums = [2,3,1,2,4,3] 输出:2 解释:子数组 [4,3] 是该条件下的长度最小的子数组。
public int minSubArrayLen(int target, int[] nums) { int i=0,sum=0,result=Integer.MAX_VALUE; for(int j=0;j<nums.length;j++){ sum=sum+nums[j]; while (sum>=target){ int m = j - i + 1; sum=sum-nums[i]; i++; result=Math.min(result,m); } } if(result==Integer.MAX_VALUE) return 0; return result; }
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
1. 输入: s = "abcabcbb" 2. 输出: 3 3. 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
public int lengthOfLongestSubstring(String s) { if(s==null||s.equals("")) return 0; int i=0,max=0; HashSet<Character> hashSet=new HashSet<>(); for(int j=0;j<s.length();j++){ if(!hashSet.contains(s.charAt(j))){ int m = j - i + 1; max=Math.max(m,max); hashSet.add(s.charAt(j)); } else{ while (hashSet.contains(s.charAt(j))){ hashSet.remove(s.charAt(i)); i++; } hashSet.add(s.charAt(j)); } } return max; }
给你一个整数数组 nums 和一个整数 k ,判断数组中是否存在两个 不同的索引 i 和 j ,满足 nums[i] == nums[j] 且 abs(i - j) <= k 。如果存在,返回 true ;否则,返回 false 。
输入:nums = [1,2,3,1], k= 3 输出:true
public boolean containsNearbyDuplicate(int[] nums, int k) { int i=0; HashSet<Integer> hashSet=new HashSet<>(); for(int j=0;j<nums.length;j++){ if(j-i>k){ hashSet.remove(nums[i]); i++; } if(!hashSet.contains(nums[j])){ hashSet.add(nums[j]); } else return true; } return false; }