滑动窗口

[Algo] 滑动窗口

1. 长度最小的子数组

// 1. 长度最小的子数组
// https://leetcode.cn/problems/minimum-size-subarray-sum/description/
int minSubArrayLen(int target, vector<int>& nums) {
    int ans = INT32_MAX;
    for (int l = 0, r = 0, sum = 0; r < nums.size(); r++)
    {
        sum += nums[r];
        while (sum - nums[l] >= target) sum -= nums[l++];
        if (sum >= target) ans = min(ans, r - l + 1);
    }
    return ans == INT32_MAX ? 0 : ans;
}

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

// 2. 无重复字符的最长子串
// https://leetcode.cn/problems/longest-substring-without-repeating-characters/
int lengthOfLongestSubstring(string str) {
    int ans = 0;
    set<char> s;
    bool flag;
    for (int l = 0, r = 0; r < str.length(); r++)
    {
        if (s.find(str[r]) != s.end()) flag = true;
        else flag = false;
        if (flag) 
        {
            while (str[l] != str[r]) s.erase(str[l++]);
            s.erase(str[l++]);
        }
        s.insert(str[r]);
        ans = max(ans, r - l + 1);
    }
    return ans;
}

3. 最小覆盖子串

// 3. 最小覆盖子串
// https://leetcode.cn/problems/minimum-window-substring/description/
string minWindow(string s, string t) {
    int arr[256] = {0};
    for (int i = 0; i < t.length(); i++) arr[t[i]]--;
    int debt = t.length();
    int len = INT32_MAX, start = 0;
    for (int l = 0, r = 0; r < s.length(); r++)
    {
        if (arr[s[r]]++ < 0) debt--;
        if (debt == 0)
        {
            while (arr[s[l]] > 0) arr[s[l++]]--;
            if (r - l + 1 < len)
            {
                len = r - l + 1;
                start = l;
            }
        }
    }
    if (len == INT32_MAX) return "";
    return s.substr(start, len);
}

4. K个不同整数的子数组

int subarraysWithNoMoreThanKDistinct(vector<int>& nums, int k);
// 4. K个不同整数的子数组
// https://leetcode.cn/problems/subarrays-with-k-different-integers/
int subarraysWithKDistinct(vector<int>& nums, int k) {
    return subarraysWithNoMoreThanKDistinct(nums, k) - subarraysWithNoMoreThanKDistinct(nums, k - 1);
}
int subarraysWithNoMoreThanKDistinct(vector<int>& nums, int k)
{
    int arr[20001] = {0};
    int cnt = 0, ans = 0;
    for (int l = 0, r = 0; r < nums.size(); r++)
    {
        if (++arr[nums[r]] == 1) cnt++;
        while (cnt > k)
        {
            if (--arr[nums[l++]] == 0) cnt--;
        }
        ans += r - l + 1;
    }
    return ans;
}

5. 至少有K个重复字符的最长子串

// 5. 至少有K个重复字符的最长子串
// https://leetcode.cn/problems/longest-substring-with-at-least-k-repeating-characters/description/
int longestSubstring(string s, int k) {
    int ans = 0;
    for (int require = 1; require <= 26; r++)
    {
        // require 种字符
        int arr[256] = {0};
        for (int l = 0, r = 0, collect = 0, satisfy = 0; require < s.length(); r++)
        {
            // collect 总收集到的字符种数, satisfy 满足条件的字符种数
            arr[s[r]]++;
            if (arr[s[r]] == 1) collect++;
            if (arr[s[r]] == k) satisfy++;
            while (collect > require)
            {
                if (arr[s[l]] == 1) collect--;
                if (arr[s[l]] == k) satisfy--;
                arr[s[l++]]--;
            }
            if (satisfy == require) ans = max(ans, r - l + 1);
        }
    }
    return ans;
}
posted @ 2024-12-22 14:33  yaoguyuan  阅读(18)  评论(0)    收藏  举报