算法综合篇专题二:滑动窗口

"在混沌想法中,最不可理喻念头。"


1、长度最小的子数组

(1) 题目解析

(2) 算法原理

cpp 复制代码
class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int n = nums.size();
        int sum = 0;
        int len = INT_MAX;
        for(int left=0,right=0;right<n;++right)
        {
            // 1.入窗口
            sum += nums[right];
            // 2.判断
            while(sum >= target) 
            {
                // 3.更新结果
                len = min(len,right-left+1);
                // 4.出窗口
                sum -= nums[left++];
            }
        }
        return len == INT_MAX ? 0:len;
    }
};

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

(1) 题目解析

(2) 算法原理

cpp 复制代码
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int n = s.size();
        int hashtable[128] = {0};
        int len = 0;
        for(int left=0,right=0;right<n;++right)
        {
            //1.入窗口:进入哈希表
            hashtable[s[right]]++;
            // 2.判断:出现重复字符
            while(hashtable[s[right]] > 1) 
                // 3.出窗口:过滤冲突字符
                hashtable[s[left++]]--;
            // 4.更新长度
            len = max(len,right-left+1);
        }
        return len;
    }
};

3、最大连续1的个数Ⅲ

(1) 题目解析

(2) 算法原理

cpp 复制代码
class Solution {
public:
    int longestOnes(vector<int>& nums, int k) {
        int n = nums.size();
        int max_num = 0;
        for(int left=0,right=0,count=0;right<n;++right)
        {
            // 1.入窗口 对0做特殊处理
            if(nums[right] == 0) count++;

            // 2.判断:0的个数多了
            while(count > k){
                // 3. 出窗口:让left指向第一个遇到0位置的下一个
                if(nums[left++] == 0) count--;
            }
            // 4.更新结果
            max_num = max(max_num,right - left + 1);
        }
        return max_num;
    }
};

4、 将 x 减到0的最小操作数

(1) 题目解析

(2) 算法原理

cpp 复制代码
class Solution {
public:
    int minOperations(vector<int>& nums, int x) {
        int n = nums.size();
        int sum = 0;
        for(auto& e:nums) sum+=e;
        int tar = sum - x;
        if(tar < 0) return -1;

        int tmp = 0;
        int op_num = -1;
        for(int left=0,right=0;right<n;++right)
        {
            // 1.入窗口
            tmp += nums[right];
            // 2.判断
            while(tmp > tar)
                // 4.出窗口
                tmp -= nums[left++];
            // 3.结果更新
            if(tmp == tar) op_num = max(op_num,right-left+1);
        }

        if(op_num == -1) return -1;
        else return n - op_num;
    }
};

5、水果成篮

(1) 题目解析

(2) 算法原理

cpp 复制代码
class Solution {
public:
    int totalFruit(vector<int>& fruits) {
        int n = fruits.size();
        unordered_map<int,int> hash;
        int ret = 0;
        for(int left=0,right=0;right<n;++right)
        {
            // 1.入窗口
            int in = fruits[right];
            hash[in]++;

            // 2.判断
            while(hash.size() > 2)
            {
                // 4.出窗口
                int out = fruits[left];
                hash[out]--;
                // 移除
                if(hash[out] == 0) hash.erase(out);
                left++;
            }
            // 3.更新结果
            ret = max(ret,right-left+1);
        }
        return ret;
    }
};

优化:

cpp 复制代码
class Solution {
public:
    int totalFruit(vector<int>& fruits) {
        int hashtable[100001] = {0};
        int n = fruits.size();
        int ret = 0;
        // kinds:记录[left,right]种类数
        for(int left=0,right=0,kinds=0;right<n;++right)
        {
            // 1.入窗口 && 维护kinds
            if(hashtable[fruits[right]] == 0) kinds++;
            hashtable[fruits[right]]++;

            // 2.判断
            while(kinds > 2)
            {
                // 4.出窗口
                hashtable[fruits[left]]--;
                // 移除
                if(hashtable[fruits[left]] == 0) kinds--;
                left++;
            }
            // 3.更新结果
            ret = max(ret,right-left+1);
        }
        return ret;
    }
};

6、找到字符串中所有字母异位词

(1) 题目解析

(2) 算法原理

cpp 复制代码
class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        vector<int> res;
        int hash1[26] = {0};
        for(auto& ch:p) hash1[ch-'a']++;

        int hash2[26] = {0};
        int m = p.size();
        for(int left=0,right=0,count=0;right<s.size();++right)
        {
            char in = s[right];
            if(++hash2[in-'a'] <= hash1[in-'a']) count++;

            if(right-left+1>m)
            {
                char out = s[left++];
                if(hash2[out-'a']-- <= hash1[out-'a']) count--;
            }

            if(count == m) res.push_back(left);
        }
        return res;
    }
};

7、串联所有单词的子串

(1) 题目解析

进行这样的转换,这道题难道不像上一题的异位词?所以,我们是采用上一题的实现这一题的解法。

(2) 算法原理

cpp 复制代码
class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        int n = s.size();
        int len = words[0].size(); // 步长
        int m = words.size(); // 长度
        
        unordered_map<string,int> hash1;
        for(auto& str:words) hash1[str]++;

        vector<int> res;
        for(int i=0;i<len;++i)
        {
            // 维护单词滑动窗口
            unordered_map<string,int> hash2;
            // right+len 处理边界问题
            for(int left=i,right=i,count=0;right + len <= n;right+=len)
            {
                // 1.入窗口:向后移动len
                string in = s.substr(right,len);
                hash2[in]++;
                if(hash1.count(in) && hash1[in] >= hash2[in]) count++; //有效字符

                // 2.判断
                if(right - left + 1 > len * m) //
                {
                    // 3.出窗口
                    string out = s.substr(left,len);
                    if(hash1.count(out) && hash1[out] >= hash2[out]) count--;
                    hash2[out]--;
                    left += len;
                }

                if(count == m) res.push_back(left);
            }
        }
        return res;
    }
};

8、最小覆盖子串

(1) 题目解析

(2) 算法原理

cpp 复制代码
class Solution {
public:
    string minWindow(string s, string t) {
        int hash1[128] = {0};
        int kinds = 0;
        for(auto& ch:t) if(hash1[ch]++ == 0) kinds++;
        
        int hash2[128] = {0};
        int begin=-1,minlen=INT_MAX;

        // count用来记录[left,right]有效字符
        for(int left=0,right=0,count=0;right<s.size();++right)
        {
            // 1.入窗口 && count维护
            char in = s[right];
            // 滤过多余字符
            if(hash1[in] == ++hash2[in]) count++;
            // 2.结果更新
            while(count == kinds)
            {
                if(minlen > right - left + 1 ){
                    begin = left;
                    minlen = right - left + 1;
                }

                char out = s[left++];
                // 滤过多余字符
                if(hash1[out] == hash2[out]--) count--;
            }
        }

        if(begin == -1) return "";
        else return s.substr(begin,minlen);
    }
};

本篇到此结束,感谢你的阅读。

祝你好运,向阳而生~

相关推荐
Amor风信子7 分钟前
华为OD机试真题---跳房子II
java·数据结构·算法
戊子仲秋25 分钟前
【LeetCode】每日一题 2024_10_2 准时到达的列车最小时速(二分答案)
算法·leetcode·职场和发展
邓校长的编程课堂27 分钟前
助力信息学奥赛-VisuAlgo:提升编程与算法学习的可视化工具
学习·算法
sp_fyf_202443 分钟前
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-03
人工智能·算法·机器学习·计算机视觉·语言模型·自然语言处理
Eric.Lee20211 小时前
数据集-目标检测系列- 螃蟹 检测数据集 crab >> DataBall
python·深度学习·算法·目标检测·计算机视觉·数据集·螃蟹检测
林辞忧1 小时前
算法修炼之路之滑动窗口
算法
￴ㅤ￴￴ㅤ9527超级帅2 小时前
LeetCode hot100---二叉树专题(C++语言)
c++·算法·leetcode
liuyang-neu2 小时前
力扣 简单 110.平衡二叉树
java·算法·leetcode·深度优先
penguin_bark2 小时前
LCR 068. 搜索插入位置
算法·leetcode·职场和发展
_GR2 小时前
每日OJ题_牛客_牛牛冲钻五_模拟_C++_Java
java·数据结构·c++·算法·动态规划