LeetCode-滑动窗口

1 滑动窗口介绍

        滑动窗口主要用来解决连续序列的问题,也就是子数组和子字符串相关的问题。滑动窗口的滑动条件就是题目的要求,滑动条件可以借助有序的set、multiset或者无序的unordered_set等来实现。

        子数组和子字符串相关问题:CSDN

        同时对比子序列和字符串序列的相关问题:CSDN

2 力扣题目

2.1 滑动窗口平均值

剑指 Offer II 041. 滑动窗口的平均值

class MovingAverage {
public:
    int s;
    double sum;
    queue q;
    /** Initialize your data structure here. */
    MovingAverage(int size) {
        s = size;
        sum = 0;
    }
    
    double next(int val) {
        if (q.size() < s)
        {
            sum += val;
            q.push(val);
            return sum / q.size();
        }
        else
        {
            sum -= q.front();
            q.pop();
            sum += val;
            q.push(val);
            return sum / s;
        }
    }
};

/**
 * Your MovingAverage object will be instantiated and called as such:
 * MovingAverage* obj = new MovingAverage(size);
 * double param_1 = obj->next(val);
 */

2.2 最近请求次数

剑指 Offer II 042. 最近请求次数

class RecentCounter {
public:
    queue q;
    RecentCounter() {
        
    }
    
    int ping(int t) {
        while (!q.empty())
        {
            int diff = t - q.front();
            if (diff > 3000)
                q.pop();
            else
                break;
        }
        q.push(t);

        return q.size();
    }
};

/**
 * Your RecentCounter object will be instantiated and called as such:
 * RecentCounter* obj = new RecentCounter();
 * int param_1 = obj->ping(t);
 */

2.3 存在重复元素

220. 存在重复元素 III

剑指 Offer II 057. 值和下标之差都在给定的范围内

2.3.1 滑动窗口

class Solution {
public:
    bool containsNearbyAlmostDuplicate(vector& nums, int k, int t) {
        //相当于用set维护一个窗口
        set st;
        for (int i = 0; i < nums.size(); i ++) 
        {
            //[nums[i]-t, nums[i]+t]
            auto a = st.lower_bound((long) nums[i] - t);
            if (a != st.end() && *a <= (long)nums[i] + t) 
            {
                return true;
            }
            st.insert(nums[i]);
            if (i >= k)
                st.erase(nums[i-k]);
        }
        return false;
    }
};

2.3.2 哈希

class Solution {
public:
    bool containsNearbyAlmostDuplicate(vector& nums, int k, int t) {        
        unordered_map> m;
        int n = nums.size();
        for (int i=0;i

2.4 最长不含重复字符的子字符串

3. 无重复字符的最长子串

剑指 Offer 48. 最长不含重复字符的子字符串

剑指 Offer II 016. 不含重复字符的最长子字符串

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        unordered_set w;
        int left = 0, right = 0, len = 0;
        while(right < s.length())
        {
            char c = s[right];
            if (w.count(c))
            {
                len = std::max(len, right - left);                
                w.erase(s[left++]);
                continue;
            }
            else
            {
                w.insert(c);
            }
            ++right;
        }

        len = std::max(len, right - left);
        return len;
    }
};

动态规划的另外一种解法:

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        vector dp(128,-1);//存储每个字符最后出现的位置
        int i=0,j=0,res=0;
        for(;j

2.5 绝对差不超过限制的最长连续子数组

1438. 绝对差不超过限制的最长连续子数组

//链接:https://leetcode-cn.com/problems/longest-continuous-subarray-with-absolute-diff-less-than-or-equal-to-limit/solution/jue-dui-chai-bu-chao-guo-xian-zhi-de-zui-5bki/
class Solution {
public:
    int longestSubarray(vector& nums, int limit) {
        //数组中可能存在重复的数据,所以使用multiset
        multiset s;
        int n = nums.size();
        int left = 0, right = 0;
        int ret = 0;
        while (right < n) 
        {
            s.insert(nums[right]);
            while (*s.rbegin() - *s.begin() > limit) 
            {
                s.erase(s.find(nums[left++]));
            }
            ret = max(ret, right - left + 1);
            right++;
        }
        return ret;
    }
};

2.6 滑动窗口的中位数

480. 滑动窗口中位数

class Solution {
public:
    vector medianSlidingWindow(vector& nums, int k) {
        vector r;
        multiset s;//因为需要排序且可能存在重复的数据,所以选择multiset
        int left = 0;        

        for(auto& i : nums)
        {
            s.insert(i);
            if (s.size() < k)
            {
                continue;
            }
            else if (s.size() > k)
            {
                //这里是关键,题目https://leetcode-cn.com/problems/longest-continuous-subarray-with-absolute-diff-less-than-or-equal-to-limit/ 与此操作类似
                s.erase(s.find(nums[left++]));
            }

            auto it = s.begin();
            double mid = 0.0;
            if (k & 0x01 == 1)
            {
                std::advance(it, k/2);
                mid = *it;
            }
            else
            {
                std::advance(it, k/2-1);
                mid += *it;
                std::advance(it, 1);
                mid += *it;
                mid /= 2;
            }
            
            r.push_back(mid);            
        }

        return r;
    }
};

2.7 最小覆盖子串

76. 最小覆盖子串

//从leetcode 567 https://leetcode-cn.com/problems/permutation-in-string/ 中的方法二修改而来
//因为方法二不要求字符串中全部是小写字母
class Solution {
public:
    string minWindow(string s, string t) {
        //方法一
        string result;
		unordered_map need, window;
		for (int i = 0;i

2.8 字符串的排列

567. 字符串的排列

/*
滑动窗口
由于排列不会改变字符串中每个字符的个数,所以只有当两个字符串每个字符的个数均相等时,一个字符串才是另一个字符串的排列。

根据这一性质,记 s1 的长度为 n,我们可以遍历 s2 中的每个长度为 n 的子串,判断子串和 s1 
中每个字符的个数是否相等,若相等则说明该子串是 s1 的一个排列。

使用两个数组 cnt1 和 cnt2, cnt1 统计 s1 中各个字符的个数,cnt2统计当前遍历的子串中各个字符的个数。

由于需要遍历的子串长度均为 n,我们可以使用一个固定长度为n 的滑动窗口来维护 cnt2 :
滑动窗口每向右滑动一次,就多统计一次进入窗口的字符,少统计一次离开窗口的字符。
然后,判断 cnt1 是否与 cnt2相等,若相等则意味着 s1 的排列之一是 s2 的子串。

https://leetcode-cn.com/problems/permutation-in-string/solution/zi-fu-chuan-de-pai-lie-by-leetcode-solut-7k7u/
*/

class Solution {
public:
    bool checkInclusion(string s1, string s2) {
        //方法一
        // int n = s1.length(), m = s2.length();
        // if (n > m) {
        //     return false;
        // }
        // vector cnt1(26), cnt2(26);
        // for (int i = 0; i < n; ++i) {
        //     ++cnt1[s1[i] - 'a'];
        //     ++cnt2[s2[i] - 'a'];
        // }
        // if (cnt1 == cnt2) {
        //     return true;
        // }
        // for (int i = n; i < m; ++i) {
        //     ++cnt2[s2[i] - 'a'];
        //     --cnt2[s2[i - n] - 'a'];
        //     if (cnt1 == cnt2) {
        //         return true;
        //     }
        // }
        // return false;

        //方法二,速度稍低于方法一
		unordered_map need, window;
		for (int i = 0;i

2.9 找到字符串中的所有字母异位词

438. 找到字符串中所有字母异位词

class Solution {
public:
    vector findAnagrams(string s, string p) {
        vector r;
        do 
        {
            int n = p.length(), m = s.length();
            if (n > m) 
            {
                break;
            }

            vector cnt1(26), cnt2(26);
            for (int i = 0; i < n; ++i) 
            {
                ++cnt1[p[i] - 'a'];
                ++cnt2[s[i] - 'a'];
            }

            if (cnt1 == cnt2) 
            {
                r.push_back(0);
            }
            
            for (int i = n; i < m; ++i) 
            {
                ++cnt2[s[i] - 'a'];
                --cnt2[s[i - n] - 'a'];
                if (cnt1 == cnt2) 
                {
                    r.push_back(i-n+1);
                }
            }
        }while(0);

        return r;        
    }
};

2.10 重复的DNA序列

187. 重复的DNA序列

class Solution {
public:
    vector findRepeatedDnaSequences(string s) {
        int n = s.length();
        unordered_map m;
        unordered_set st;
        for (int i=0;i<=n-10;++i)
        {
            string str = s.substr(i,10);
            if (m.count(str))
                st.insert(str);
            m[str]++;
        }
        return vector(st.begin(), st.end());
    }
};

2.11 最长连续递增序列

674. 最长连续递增序列

//使用滑动窗口
class Solution {
public:
    int findLengthOfLCIS(vector& nums) {
        int maxLen = 1, left = 0, right = 0;
        for (;right < nums.size();++right)
        {
            if (right > 0)
            {
                if (nums[right] > nums[right-1])
                    maxLen = std::max(maxLen, right-left+1);
                else
                    left = right;
            }
        }

        return maxLen;
    }
};

2.12

2.13

2.14

2.15

2.16

2.17

2.18

2.19

你可能感兴趣的:(#,LeetCode-滑动窗口,算法)