专题二:滑动窗口【优选算法】

news/2024/7/24 10:14:22 标签: 算法, java, 数据结构

滑动窗口:

什么时候用? 同向双指针(找单调性)

怎么用?

1)用left、right指针维护窗口

2)进窗口(right指针++,更新窗口内的值)

3)判断

        出窗口(left++,并更新窗口内的值)

4)更新结果(注意每道题更新结果的时机不同,需具体分析)

目录

滑动窗口:

1、长度最小的子数组

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

3、最大连续1的个数 

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

5、水果成篮

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

7、串联所有单词的子串(容器的使用)

8、最小覆盖子串 


1、长度最小的子数组

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int n = nums.size();
        int sum = 0,len = INT_MAX;
        for(int l = 0,r = 0;r < n;r++){
            sum += nums[r];//入窗口
            while(sum >= target)//判断
            {
                len = min(len,r - l + 1);//更新结果
                sum -= nums[l++];//出窗口
            }
        }    
        return len == INT_MAX?0:len;    
    }
};

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

 暴力解法,枚举每一个字串,但分析可发现,出现重复字符时,left可直接跳到重复字符,right也无需往回走。因此就是同向双指针,也就是滑动窗口。

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        vector<int> hash(128);//用来判断字符是否出现过
        int len = 0,n = s.size();
        for(int l = 0,r = 0;r < n;r++){//进窗口
            hash[s[r]]++;
            while(hash[s[r]] > 1)//判断
            {
                hash[s[l]]--;//出窗口
                l++;
            }
            len = max(len,r-l+1);//更新结果
        }
        return len;
    }
};

3、最大连续1的个数 

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

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

 

通过正难则反,可以将此题转换成类似第一题 

class Solution {
public:
    int minOperations(vector<int>& nums, int x) {
        int n = nums.size();
        int sum = 0;
        for(auto x : nums){
            sum += x;
        }
        int target = sum - x;

        if(target < 0) return -1;
        int ret = -1,sum2 = 0;
        for(int left = 0,right = 0;right < n;right++){
            sum2 += nums[right];
            while(sum2 > target) sum2 -= nums[left++];
            if(sum2 == target) ret = max(ret,right - left + 1);
        }
        return ret == -1?-1:n - ret;
    }
};

5、水果成篮

 unordered_map版

class Solution {
public:
    int totalFruit(vector<int>& fruits) {
        unordered_map<int,int> hash;
        int n = fruits.size();
        int kind = 0,ret = 0;
        for(int left = 0,right= 0;right < n;right++){
            hash[fruits[right]]++;

            while(hash.size() > 2)
            {
                hash[fruits[left]]--;
                if(hash[fruits[left]] == 0) hash.erase(fruits[left]);
                left++;
            }
            ret = max(ret,right - left + 1);
        }
        return ret;
    }
};

数组版: 

class Solution {
public:
    int totalFruit(vector<int>& fruits) {
        int hash[100010] = {0};
        int n = fruits.size();
        int kind = 0,ret = 0;
        for(int left = 0,right= 0;right < n;right++){
            if(hash[fruits[right]] == 0) kind++;
            hash[fruits[right]]++;

            while(kind > 2)
            {
                hash[fruits[left]]--;
                if(hash[fruits[left]] == 0) kind--;
                left++;
            }
            ret = max(ret,right - left + 1);
        }
        return ret;
    }
};

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

check的优化: 

class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        int hashp[265] = {0};
        for(auto x : p) hashp[x]++;
        int count = 0;
        vector<int> ret;
        int hashs[256] = {0};
        for(int l = 0,r = 0;r < s.size();r++){
            hashs[s[r]]++;
            if(hashs[s[r]] <= hashp[s[r]]) count++;
            if(r - l + 1 > p.size())
            {
                if(hashs[s[l]] <= hashp[s[l]]) count--;
                hashs[s[l]]--;
                l++;
            }
            if(count == p.size()) ret.push_back(l);
        }
        return ret;
    }
};

7、串联所有单词的子串(容器的使用)

 

class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        unordered_map<string,int> hash1;
        vector<int> ret;
        for(auto& s:words){
            hash1[s]++;
        }
        int len = words[0].size(),m = words.size();
        for(int i = 0;i < len;i++){
            unordered_map<string,int> hash2;
            for(int left = i,right = i,count= 0; right + len <= s.size();right += len){
                //进窗口+维护count
                string in = s.substr(right,len);
                hash2[in]++;
                if(hash2[in] <= hash1[in]) count++;
                //判断
                if(right - left + 1 > len * m) 
                {
                    //出窗口+维护count
                    string out = s.substr(left,len);
                    if(hash2[out] <= hash1[out]) count--;   
                    hash2[out]--;
                    left += len;
                }
                //更新结果
                if(count == m) ret.push_back(left);
            }
        }
        return ret;
    }
};

8、最小覆盖子串 

 

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++;
            hash1[ch]++;
        }
        int hash2[128] = {0};

        int minlen = INT_MAX,begin = -1;

        for(int left = 0,right = 0,count = 0;right < s.size();right++){
            //进窗口
            char in = s[right];
            hash2[in]++;
            if(hash2[in] == hash1[in]) count++;
            while(count == kinds)
            {
                if(right - left+1 < minlen)
                {
                    minlen = right - left + 1;
                    begin = left;
                }
                char out = s[left++];
                if(hash2[out] == hash1[out]) count--;
                hash2[out]--;
            }
        }
        if(begin == -1) return "";
        else return s.substr(begin,minlen);
    }
};

 


http://www.niftyadmin.cn/n/5110005.html

相关文章

ReentrantLock与synchronized区别之比较(面试)

背景&#xff1a; 我们Java开发中需要保证数据线程安全时有多重选择&#xff0c;直接使用线程安全的集合类&#xff0c;或者某些变量我们通过ReentrantLock来保证安全&#xff0c;或者使用synchronized关键字&#xff0c;那两者有何区别&#xff1f; 备注&#xff1a; Reent…

2023年中国工业空气加热器市场规模及存在问题分析[图]

工业空气加热器行业是指涉及工业领域中空气加热设备的制造、销售、安装和维护的产业。这个行业专注于生产用于加热空气的设备&#xff0c;以满足工业生产过程中的加热需求。工业空气加热器可以采用各种不同的加热技术&#xff0c;如电加热、燃气加热、蒸汽加热等&#xff0c;用…

基于springboot实现财务管理系统项目【项目源码+论文说明】

基于springboot实现财务管理系统演示 摘要 随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理系统应运而生&#x…

8.2 C++ 引用与取别名

C/C语言是一种通用的编程语言&#xff0c;具有高效、灵活和可移植等特点。C语言主要用于系统编程&#xff0c;如操作系统、编译器、数据库等&#xff1b;C语言是C语言的扩展&#xff0c;增加了面向对象编程的特性&#xff0c;适用于大型软件系统、图形用户界面、嵌入式系统等。…

【Arduino TFT】基于 ESP32S3 S7789 240x240 TFT实现的龙猫太空人天气时钟

忘记过去&#xff0c;超越自己 ❤️ 博客主页 单片机菜鸟哥&#xff0c;一个野生非专业硬件IOT爱好者 ❤️❤️ 本篇创建记录 2023-10-21 ❤️❤️ 本篇更新记录 2023-10-21 ❤️&#x1f389; 欢迎关注 &#x1f50e;点赞 &#x1f44d;收藏 ⭐️留言&#x1f4dd;&#x1f64…

安装与脏数据绕过_安全狗

1安全狗 1.1 环境准备 安全狗safedogwzApacheV3.5.exe&#xff0c;安装步骤省略&#xff0c; pikachu环境&#xff1a;https://zhuanlan.zhihu.com/p/568493971 安装注意事项&#xff1a;安装完后php和web服务都需要重启 注意事项&#xff1a;服务名php版本保持一致 安装过…

基于springboot实现财务管理系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现财务管理系统演示 摘要 随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理系统应运而生&#x…

【解锁未来】探索Web3的无限可能性-01

文章目录 前言什么是Web3&#xff1f; 前言 还记得你第一次听说比特币吗&#xff1f;也许那只是一个关于新技术将改变一切的微弱嗡嗡声。也许你会有一种 "FOMO "的感觉&#xff0c;因为那些早早入场的人突然积累了一大笔财富–尽管你并不清楚这些 "钱 "可…