滑动窗口问题

PS:以下代码皆为C++代码实现

1.什么是滑动窗口

假设有两个同向指针,一个左指针,一个右指针,右指针在移动的同时。左指针不变,当到达判断条件的时候,左指针开始移动,左右指针形成一个窗口,当左右指针移动的时候,窗口移动,这就是滑动窗口问题。做这种题基本思路为:

  • 判断进窗口位置
  • 判断出窗口位置
  • 返回结果

2.题目

2.1 长度最小的子数组  力扣

给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。

示例 1:

输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。

示例 2:

输入:target = 4, nums = [1,4,4]
输出:1

示例 3:

输入:target = 11, nums = [1,1,1,1,1,1,1,1]
输出:0

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/minimum-size-subarray-sum

class Solution {
public:
    int minSubArrayLen(int target, vector& nums) 
    {
        int sum=0,len=INT_MAX;
        int n=nums.size();
        for(int left=0,right=0;right=target)//判断条件+维护
            {
                sum-=nums[left];
                len=min(len,right-left+1);//返回结果
                left++;
            }
        }       
        return len==INT_MAX?0:len;//返回结果
    }
};

2.2 无重复字符的最长字串  力扣

给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。

示例 1:

输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

示例 2:

输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。

示例 3:

输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
     请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/longest-substring-without-repeating-characters

class Solution {
public:
    int lengthOfLongestSubstring(string s) 
    {
        
        int len=0;
        int n=s.size();
        int hash[128]={0};
        for(int left=0,right=0;right1)//判断条件
            {
                hash[s[left]]--;
                left++;//出窗口
            }
            len=max(len,right+1-left);//更新结果
        }
        return len;//返回值
    }
};

2.3  最大连续1的个数3 力扣

给定一个二进制数组 nums 和一个整数 k,如果可以翻转最多 k 个 0 ,则返回 数组中连续 1 的最大个数 。

示例 1:

输入:nums = [1,1,1,0,0,0,1,1,1,1,0], K = 2
输出:6
解释:[1,1,1,0,0,1,1,1,1,1,1]
粗体数字从 0 翻转到 1,最长的子数组长度为 6。

示例 2:

输入:nums = [0,0,1,1,0,0,1,1,1,0,1,1,0,0,0,1,1,1,1], K = 3
输出:10
解释:[0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1]
粗体数字从 0 翻转到 1,最长的子数组长度为 10。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/max-consecutive-ones-iii

class Solution {
public:
    int longestOnes(vector& nums, int k) 
    {
        int n=nums.size();
        int ZenoNum=0;
        int count=0;
        for(int left=0,right=0;rightk)//判断条件
            {
                if(nums[left]==0)
                {
                    ZenoNum--;//出窗口条件     
                }  
                left++;
              
            } 
            count=max(count,right+1-left);  //更新结果  
        }
        return count;
    }
};

2.4  将x减到0的最小操作数 力扣

给你一个整数数组 nums 和一个整数 x 。每一次操作时,你应当移除数组 nums 最左边或最右边的元素,然后从 x 中减去该元素的值。请注意,需要 修改 数组以供接下来的操作使用。

如果可以将 x 恰好 减到 0 ,返回 最小操作数 ;否则,返回 -1 。

示例 1:

输入:nums = [1,1,4,2,3], x = 5
输出:2
解释:最佳解决方案是移除后两个元素,将 x 减到 0 。

示例 2:

输入:nums = [5,6,7,8,9], x = 4
输出:-1

示例 3:

输入:nums = [3,2,20,1,1,3], x = 10
输出:5
解释:最佳解决方案是移除后三个元素和前两个元素(总共 5 次操作),将 x 减到 0 。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/minimum-operations-to-reduce-x-to-zero

class Solution {
public:
    int minOperations(vector& nums, int x) 
    {
        //反向求最长的操作数,然后减去最长操作数的长度
        int n=nums.size();
        int target=0;
        int sum=0;
        for(auto sh:nums) sum+=sh;
        int len=-1;
        if((sum-x)<0) return -1;
        for(int left=0,right=0;right(sum-x))//进窗口
            {
                target-=nums[left];
                //出窗口
                left++;
            }
            if(target==(sum-x))//等于更新
                len=max(len,right-left+1);
        }
       
       if((n-len)>n) return -1;
        return n-len;
    }
};

2.5  找到所有字符串中的异位词   力扣

输入: s = "cbaebabacd", p = "abc"
输出: [0,6]
解释:
起始索引等于 0 的子串是 "cba", 它是 "abc" 的异位词。
起始索引等于 6 的子串是 "bac", 它是 "abc" 的异位词。

 示例 2:

输入: s = "abab", p = "ab"
输出: [0,1,2]
解释:
起始索引等于 0 的子串是 "ab", 它是 "ab" 的异位词。
起始索引等于 1 的子串是 "ba", 它是 "ab" 的异位词。
起始索引等于 2 的子串是 "ab", 它是 "ab" 的异位词。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/find-all-anagrams-in-a-string

class Solution {
public:
    vector findAnagrams(string s, string p) 
    {
        int hash1[26]={0};
        for(auto ch: p) hash1[ch-'a']++;//统计字符串中出现的字符个数
        int n=p.size();
        int hash2[26]={0};
        vector ret;
        for(int left=0,right=0,count=0;rightn)
            {  
                    char out=s[left];
                    left++;
                    if(hash2[out-'a']--<=hash1[out-'a'])//出窗口+维护
                    {
                        //hash2[s[left]-'a']--;
                        count--;
                    }
            }
            if(n==count) ret.push_back(left);
        }
        return ret;
    }
};

你可能感兴趣的:(数据结构)