C++算法之滑动窗口算法1
·
209.长度最小的子数组

解法一:使用暴力枚举
但是及其容易超时
int minSubArrayLen(int target, int* nums, int numsSize) {
int mintargetsize = 0;
for(int i =0;i < numsSize;i++)
{
int targetsize = 0;
int sum = 0;
int j = i;
while(sum <target && j <numsSize)
{
sum += nums[j];
j++;
targetsize++;
}
if(sum >= target)
{
if(mintargetsize == 0)
{
mintargetsize = targetsize;
}
else if(targetsize < mintargetsize)
{
mintargetsize = targetsize;
}
}
}
return mintargetsize;
}
解法二:利用单调性,使用同向双指针来优化
所以,当我们在暴力解法中发现有利用单调性时就可以使用滑动窗口算法
在上面我们很容易注意到,当len为一个确定值时,如果我们直接拿len这个区间向右移动,当这个区间内的数不满足条件时,我们不做出改变,当我们发现len内不需要这么多数就能满足条件时,我们就可以缩小窗口,之后继续向右移动
逻辑在进窗口,判断,出窗口,更新结果之间进行移动
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int n = nums.size(),sum = 0,ret = INT_MAX;
for(int left = 0,right =0; right < n; right++)
{
sum += nums[right];//进窗口
while(sum >= target)
{
ret = min(ret,right-left+1);//更新结果
sum-=nums[left++];//出窗口
}
}
return ret == INT_MAX? 0 : ret;
}
};
3.无重复字符的最长子串

解法一:依旧暴力枚举
解法二:利用规律使用滑动动窗口解决问题
例:deabcabca
设置right指针和left指针,当第一次遇到重复字符时,left在cab处,此时第一个a在eab处,此时两个重复字符之间的距离是小于等于最大字符的长度的,就代表没有必要进行两个a之间的遍历,假如right指针不在a的话,也没有必要进行right之后,left之前的遍历,因为无论如何一定会小于最大值
1进窗口 ------让字符进入哈希表
2.判断---------窗口内出现重复字符
出窗口 -----------从窗口中删除该字符
更新结果
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int hash[128] = { 0 };//使用数组模拟哈希表
int right = 0,left = 0,len = 0 , n = s.size();
int ret = 0;
while(right < n)
{
hash[s[right]]++;//进入哈希表
while(hash[s[right]] > 1)
{
hash[s[left++]]--;
}
ret = max(ret,right-left+1);
right++;
}
return ret;
}
};
1004.最大连续1的个数III

算法原理:
转化:找出最长子数组,0的个数不超过k个

方法一:暴力枚举+zero计数器
方法二:使用滑动窗口来解决问题
1.right = 0 ,left = 0
2.进入窗口 :如果是1,无视 如果是0,计数器+1
3.判断 : zero > k
出窗口以及更新结果问题
class Solution {
public:
int longestOnes(vector<int>& nums, int k) {
int ret = 0;
for(int left = 0,right = 0,zero = 0;right <nums.size();right++)
{
if(nums[right] == 0)
{
zero++;
}
while(zero > k)
if(nums[left++] == 0) zero--;
ret = max(ret,right-left+1);
}
return ret;
}
};
更多推荐
所有评论(0)