专题二滑动窗口

双指针法的特化 具体体现在指针的同向移动维护的进出窗口 其模板就是r的在循环后的必定++与l的陆续弹出和更新结果

专题二滑动窗口

此类型关键在于 思路的优化迭代在保证r的尽量不回退的前提下与l的陆续弹出。

辅助:哈希表 解决不定的计数问题(像滑动窗口中的是否出窗口完全)。

虽然十分不提倡"模板"的解题使用但模板恰恰反应了解决此类问题的核心本质:

第一步:定义r与l维护区间for后r++。

第二步:更新结果的位置选取 (l的陆续弹出 勿跳跃前进!!!)。 //但此陆续弹出不一定指单次循环仅弹出一个。关键在于哈希表的灵活应用。

第三步:返回的最后结果的特殊情况判断。

1.两数和大于值的最小长度

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

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

以r与l维护区间以弹出和入窗口。

cpp 复制代码
class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) 
    {
        int len = INT_MAX, sum = 0;
        for(int l = 0,r = 0;r < nums.size();r++)
        {
            sum += nums[r];
            while(sum >= target)
            {
                //更新结果
                len = r - l + 1 < len? r - l + 1:len;
                sum -= nums[l++];
            }
        }
        if(len == INT_MAX)
            return 0;
        return len;
    }
};

2.无重复字符串的最小长度

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

复制代码
输入: s = "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 
"abc"所以其长度为 3。注意 "bca" 和 "cab" 也是正确答案。

1.思路:滑动窗口+哈希表

简化r的回溯过程 l的跳跃前进

r遇到重复固定 l前进至掠过重复元素期间哈希表计数--

3.将x减到0的最小操作数

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

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

利用:正难则反的编程思想。将原问题转换为求数组中间连续区域的最大长度len后以size()减去len即可。

4.水果成篮

你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果 种类

你想要尽可能多地收集水果。然而,农场的主人设定了一些严格的规矩,你必须按照要求采摘水果:

  • 你只有 两个 篮子,并且每个篮子只能装 单一类型 的水果。每个篮子能够装的水果总量没有限制。
  • 你可以选择任意一棵树开始采摘,你必须从 每棵 树(包括开始采摘的树)上 恰好摘一个水果 。采摘的水果应当符合篮子中的水果类型。每采摘一次,你将会向右移动到下一棵树,并继续采摘。
  • 一旦你走到某棵树前,但水果不符合篮子的水果类型,那么就必须停止采摘。

给你一个整数数组 fruits ,返回你可以收集的水果的 最大 数目。

简言之:找一最长区域使得区域内的数据的种数为2/1。

为什么使用哈希表 不可以使用三/四指针 因为:难以保证[left]数据弹出的完全性。

left的单次弹出与哈希表关联。

5.找到字符串子串中所有异位串

给定两个字符串 sp,找到 s中所有 p异位词的子串,返回这些子串的起始索引。不考虑答案输出的顺序。

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

利用滑动窗口维护区间 哈希表记录 zero记录滑动次数

哈希表、zero:记载完全滑动。

6.串联所有单词的字串(hard)

在了解了思路之后写不出来的原因:

1.未深入理解算法本质 模板套用未完全套用

2.缺失标记量 原有标记量难以实现模板逻辑

3.优化不足(指某个逻辑判断这么做会增大代码逻辑复杂度)

4.打草严格依据r+=len进行单次的l弹出逻辑

给定一个字符串 s和一个字符串数组 words words 中所有字符串 长度相同

s中的 串联子串 是指一个包含 words 中所有字符串以任意顺序排列连接起来的子串。

  • 例如,如果 words = ["ab","cd","ef"], 那么 "abcdef""abefcd""cdabef""cdefab""efabcd", 和 "efcdab" 都是串联子串。 "acdbef" 不是串联子串,因为他不是任何 words 排列的连接。

返回所有串联子串在 s中的开始索引。你可以以 任意顺序 返回答案。

示例 1:

复制代码
输入:s = "barfoothefoobarman", words = ["foo","bar"]
输出:[0,9]
解释:因为 words.length == 2 同时 words[i].length == 3,连接的子字符串的长度必须为 6。
子串 "barfoo" 开始位置是 0。它是 words 中以 ["bar","foo"] 顺序排列的连接。
子串 "foobar" 开始位置是 9。它是 words 中以 ["foo","bar"] 顺序排列的连接。
输出顺序无关紧要。返回 [9,0] 也是可以的。
cpp 复制代码
class Solution 
{
public:
    vector<int> findSubstring(string s, vector<string>& words) 
    {
        map<string, int> m2;
        vector<int> ret;
        for(auto e: words)
        {
            m2[e]++;
        }
        int len = words[0].size();
        for(int i = 0;i < len ;i++)
        {
            map<string, int> m1; //原串纳入
            // for(int l = i, r = i;r <= s.size()-(len*words.size()); r += len)
            for(int l = i, r = i,zero = 0;r < s.size(); r += len) 
            {
                //进窗口
                m1[s.substr(r, len)]++;
                if(m1[s.substr(r, len)] <= m2[s.substr(r, len)])//符合条件进入zero++
                    zero++;
                //出窗口 同时维护zero的值
                if(r - l + 1 > len*words.size())
                {
                    //zero更新-- 哈希退出(--) l变动

                    //有效字符的推出
                    if(m1[s.substr(l, len)] <= m2[s.substr(l, len)])
                        zero--;
                    m1[s.substr(l, len)]--;
                    // zero--;//代表有效字符啊
                    l+=len;
                }

                if(zero == words.size()) //长度符合
                    ret.push_back(l);
            }
        }
        return ret;
    }
};

7.最小覆盖子串(hard)

需要逻辑优化策略

给定两个字符串 st,长度分别是 mn,返回 s 中的 最短窗口 子串 ,使得该子串包含 t 中的每一个字符(包括重复字符 )。如果没有这样的子串,返回空字符串""

测试用例保证答案唯一。

示例 1:

复制代码
输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"
解释:最小覆盖子串 "BANC" 包含来自字符串 t 的 'A'、'B' 和 'C'。
相关推荐
tankeven2 小时前
HJ181 相差不超过k的最多数
数据结构·c++·算法
XWalnut2 小时前
LeetCode刷题 day13
数据结构·算法·leetcode
小马_xiaoen2 小时前
前端虚拟列表(Virtual List)从原理到实战:海量数据渲染终极方案
前端·数据结构·list
炽烈小老头2 小时前
【每天学习一点算法 2026/04/17】多数元素
数据结构·学习·算法
云泽8083 小时前
第十五届蓝桥杯大赛软件赛省赛C/C++大学B组
c语言·c++·算法·蓝桥杯
大模型最新论文速读3 小时前
VQKV:KV Cache 压缩 82% 性能几乎不降
人工智能·深度学习·算法·机器学习·自然语言处理
yongui478343 小时前
基于MSP430和Zigbee技术的煤矿综合监控系统设计与实现
算法
Ww.xh3 小时前
ESP8266连接AI大模型完整指南
人工智能·算法·语言模型
程序员雷欧3 小时前
Redis基础知识全解析:从数据结构到生产实战
数据结构·数据库·redis