窗口滑动算法
简介
滑动窗口算法思想是非常重要的一种思想,可以用来解决数组,字符串的子元素问题。它可以将嵌套循环的问题,转换为单层循环问题,降低时间复杂度,提高效率。
滑动窗口的思想非常简单,它将子数组(子字符串)理解成一个滑动的窗口,然后将这个窗口在数组上滑动,在窗口滑动的过程中,左边会出一个元素,右边会进一个元素,然后只需要计算当前窗口内的元素值即可。
可用滑动窗口思想解决的问题,一般有如下特点:
-
窗口内元素是连续的。就是说,抽象出来的这个可滑动的窗口,在原数组或字符串上是连续的。
-
窗口只能由左向右滑动,不能逆过来滑动。就是说,窗口的左右边界,只能从左到右增加,不能减少,即使局部也不可以。
算法思想
1.定义两个变量:right和right,用来表示两个边界。[left,right]表示窗口
2.首先right边界先扩张,到达指定的位置(根据题目来定),然后left开始扩张,直到指定的位置(依据题目来定)
3.重复上述步骤,直到right走到数组或者字符串的尾部为止
算法实现
left,right := 0,0 // 左右指针
// 窗口右边界滑动
for right < length {
window.add(s[right]) // 右元素进窗
right++ // 右指针增加
// 窗口满足条件
for valid(window) && left<right {
... // 满足条件后的操作
window.remove(arr[left]) // 左元素出窗
left++ // 左指针移动,直到窗口不满足条件
}
}
注意:
.滑动窗口适用的题目一般具有单调性
.滑动窗口、双指针、单调队列和单调栈经常配合使用
下面为例子:
1.无重复字符的最长子串
题目描述:给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
示例1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3
示例1:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串
思路
设置right和left,并且设置一个max用来求每次的最大值,使用hashSet来存放临时的子串,当right找到重复的元素时,right停止扩张,直到set删除那个重复元素为止。
代码实现
//维护当前最长不重复字符子串
Set<Character> set = new HashSet<>();
int left = 0;
int right = 0;
int max = 0;
while(right<s.length()){
if(!set.contains(s.charAt(right))){
//未查到重复字符就一直加,right右移
set.add(s.charAt(right));
right++;
}else{
//right查到重复字符先不动,left右移,set删left经过的字符,直到重复的这个字符删掉为止
set.remove(s.charAt(left));
left++;
}
//每一次计算当前set子串的长度
max = Math.max(max, set.size());
}
return max;
}
2.案例二给定一个整数数组,计算长度为k的连续子数组的最大总和。
列子:
输入:arr [] = {100,200,300,400} k = 2
输出:700
解释:300 + 400 = 700
代码实现
/**
* 输入:arr [] = {100,200,300,400} k = 2
*
* 输出:700
*
* 解释:300 + 400 = 700
* @param target
* @param nums
* @return
*/
public static void main(String[] args) {
int[] nums =new int[]{100,200,300,400};
int result = minSubArrayLen(2, nums);
System.out.println(result);
}
public static int minSubArrayLen (int k, int[] nums){
int len = nums.length;
int maxsum = 0;
for (int i = 0; i < k; i++) {
maxsum = maxsum + nums[i];
}
int sum = maxsum;
for (int i = k; i < len ; i++) {
sum = sum +nums[i] - nums[i-k];
maxsum = Math.max(sum, maxsum);
}
return maxsum;
}
标签:子串,right,窗口,nums,int,算法,滑动
From: https://www.cnblogs.com/wiseleer/p/16884094.html