
送给大家一句话:
那脑袋里的智慧,就像打火石里的火花一样,不去打它是不肯出来的。——莎士比亚
今天我学习了滑动窗口的算法思路,接下来请与我一起看看吧!!!
滑动窗口问题可以说是一种特殊的双指针问题,通常用于解决以下类型的问题:
滑动窗口算法的基本思想是使用双指针(有时也可能使用更多指针)来表示窗口的边界。在每一步中,我们可以根据特定条件来移动窗口的边界,并更新所需的统计信息。
看这些定义是真无法想象出来哦怎么个滑动窗口的,下面我们一起来做题吧:

看这个题目还是很好理解的,只需要我们找到和大于target的连续子数组,我们来看第一个样例target = 7, nums = [2,3,1,2,4,3] 显然4,3是最小的子数组。接下来分析一下算法思路:
根据题目要求,首先可以想到的是暴力枚举算法(遇事不决,暴力解决),遍历穷举出所有的连续子数组,寻找满足要求的子数组,最终就找到了最小的连续子数组:
class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums) {
//暴力解法
int n = nums.size();
if (n == 0) {
return 0;
}
//默认为最大值
int ans = INT_MAX;
//开始遍历
for (int i = 0; i < n; i++) {
//重置sum值
int sum = 0;
//判断子数组是否满足
for (int j = i; j < n; j++) {
sum += nums[j];
if (sum >= s) {
//满足就更新结果
ans = min(ans, j - i + 1);
break;
}
}
}
return ans == INT_MAX ? 0 : ans;
}
};这样暴力的算法的时间复杂度是O(n^2),我们看看可不可以进行优化: 来看图解(来着力扣官方)

这样就模拟了滑动窗口: 做法:将右端元素划⼊窗⼝中,统计出此时窗⼝内元素的和:
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int left = 0,right = 0;
//设置为最大值 保证没有满足的子数组时可以判断
int len = INT_MAX;
int sum = 0;
sum += nums[left];
while(left < nums.size() && right < nums.size()){
//
if(sum < target ){
right++;
if(right < nums.size())
sum += nums[right];
}
while (sum >= target){
len = min (right - left + 1 , len) ;
sum -= nums[left];
left++;
}
}
return len == INT_MAX ? 0:len;
}
};这样大大提高了算法的效率!!! 为何滑动窗⼝可以解决问题,并且时间复杂度更低?
这样我们不仅能解决问题,⽽且效率也会⼤⼤提升
继续我们来看下一题

描述也是十分简单奥,我们接着来看如何解决
首先想到的还是暴力枚举啊,我们可以借助哈希表来确定是否重复。 枚举过程中就会发现左右指针移动方向相同,所以可以进行滑动窗口
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int len = 0;
int n = s.size();
//使用哈希进行判断是否重复
int hash[128] = {0};
int ret = 0;
for(int left = 0,right = 0; right < n; right++){
//进入窗口
hash[s[right]]++;
//判断
while(hash[s[right]] > 1){
//出窗口
hash[s[left]]--;
left++;
len--;
}
//更新结果
len++;
ret = max(len,ret);
}
return ret;
}
};这样就完美解决。 其实滑动窗口都是可以套用上面的模版的,不信?来看下一题

题目描述依然简单奥,只是判断条件发生了改变,我们需要来定义一个数字来比较是否满足少于k
依旧是:
class Solution {
public:
int longestOnes(vector<int>& nums, int k) {
int tmp = 0,left = 0,right = 0,n = nums.size();
int ret = 0;
while(right < n){
if(nums[right] == 0) {
tmp++;
}
while(tmp > k){
if(nums[left] == 0) tmp--;
left++;
}
ret = max(ret,right - left + 1);
right++;
}
return ret;
}
};这样就成功完成解题!!!
滑动窗口问题是可以通过模版来解决:
这样基本滑动窗口都可以解决,但重要的是理解滑动窗口的思路是如何得到的,是如何从暴力算法优化出来的。
那脑袋里的智慧,就像打火石里的火花一样,不去打它是不肯出来的。——莎士比亚