C++ 滑动窗口

目录

1、209. 长度最小的子数组

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

3、1004. 最大连续1的个数 III

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

5、904. 水果成篮

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

7、30. 串联所有单词的子串

8、76. 最小覆盖子串


1、209. 长度最小的子数组

 思路:使用双指针技巧和滑动窗口的思想,通过不断调整左右指针的位置来找到和大于等于目标值的最短子数组的长度。

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int n = nums.size(), sum = 0, len = INT_MAX;
        for (int left = 0, right = 0; right < n; right++) {
            sum += nums[right];
            while (sum >= target) {
                len = min(len, right - left + 1);
                sum -= nums[left++];
            }
        }
        return len == INT_MAX ? 0 : len;
    }
};
  1. 初始化变量n为数组nums的长度,sum为0(用于记录当前子数组的和),len为INT_MAX(用于记录最短子数组的长度)。
  2. 使用双指针技巧,初始化左指针left和右指针right都指向数组的起始位置。
  3. 进入循环,循环条件是右指针right小于数组长度。
  4. 在循环中,将当前元素nums[right]加到sum中,表示扩展当前子数组。
  5. 如果sum大于等于目标值target,则进入内部循环。
  6. 在内部循环中,更新最短子数组的长度len,取当前长度right - left + 1和之前的最短长度len的较小值。
  7. 然后,从当前子数组中减去左指针所指向的元素,并将左指针向右移动一位。
  8. 重复步骤6和7,直到sum小于目标值target
  9. 返回最短子数组的长度len,如果len仍然是INT_MAX,则说明没有找到符合条件的子数组,返回0。

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

思路:通过数组模拟哈希表,每次遍历到字母时,其ASCII码值对应数组的位置加一,如果right位置出现次数大于一,则left和right对应字母相等,只需减少数组left位置减一然后left加一即可。每次遍历结束都计算与上次相比的最大长度。

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int hash[128] = {0}, n = s.size(), len = 0;
        for (int left = 0, right = 0; right < n; right++) {
            hash[s[right]]++;
            while (hash[s[right]] > 1) {
                hash[s[left++]]--;
            }
            len = max(len, right - left + 1);
        }
        return len;
    }
};

3、1004. 最大连续1的个数 III

思路:每次首先统计零出现次数,如果出现次数大于k,也就是超过可翻转0的个数时,通过while循环更新left位置。每次遍历最后计算长度。

class Solution {
public:
    int longestOnes(vector<int>& nums, int k) {
        int zero = 0, len = 0;
        for (int left = 0, right = 0; right < nums.size(); right++) {
            if (nums[right] == 0) {
                zero++;
            }
            while (zero > k) {
                if (nums[left++] == 0)
                    zero--;
            }
            len = max(len, right - left + 1);
        }
        return len;
    }
};

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

思路:寻找和等于<数组之和减x>的连续元素代替两端找元素,总长度减去其长度即为所求。

class Solution {
public:
    int minOperations(vector<int>& nums, int x) {
        int n = nums.size(), sum = 0;
        for (auto a : nums)
            sum += a;
        int target = sum - x, tmp = 0;
        if (target < 0)//处理sum小于x的情况
            return -1;
        int ret = -1;
        for (int left = 0, right = 0; right < n; right++) {
            tmp += nums[right];
            while (tmp > target)
                tmp -= nums[left++];
            if (tmp == target)
                ret = max(ret, right - left + 1);
        }
        if (ret == -1)//没有符合的返回-1
            return ret;
        else
            return n - ret;
    }
};

5、904. 水果成篮

 

 思路:哈希表+滑动窗口

class Solution {
public:
    int totalFruit(vector<int>& fruits) {
        unordered_map<int, int> hash;
        int ret = 0, n = fruits.size();
        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;
    }
};
  1. 首先,使用一个unordered_map hash来记录当前窗口中每种水果的数量。
  2. 定义一个变量ret来记录最长的连续子数组的长度,初始值为0。
  3. 使用两个指针left和right来表示窗口的左右边界,初始时两个指针都指向数组的第一个元素。
  4. 在循环中,右指针right向右移动,将当前水果加入到hash中,并增加其数量。
  5. 如果hash中不同水果的种类数大于2,说明窗口中包含了超过两种不同类型的水果,需要移动左指针left来缩小窗口。
  6. 移动左指针时,将左边界对应的水果数量减少1,并判断减少后的数量是否为0,如果为0,则从hash中删除该水果。
  7. 不断移动左指针,直到窗口中不再包含超过两种不同类型的水果。
  8. 在每次移动左指针后,更新ret的值,即为当前窗口的长度。
  9. 最后返回ret,即为最长的连续子数组的长度。

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

思路: 滑动窗口+哈希表

class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        vector<int> ret;
        int hash1[26] = {0};
        for (auto a : p) {
            hash1[a - 'a']++;
        }
        int hash2[26] = {0};
        int count = 0;
        for (int left = 0, right = 0; right < s.size(); right++) {
            char in = s[right];
            if (++hash2[in - 'a'] <= hash1[in - 'a'])
                count++;
            if (right - left + 1 > p.size()) {
                char out = s[left++];
                if (hash2[out - 'a']-- <= hash1[out - 'a'])
                    count--;
            }
            if (count == p.size())
                ret.push_back(left);
        }
        return ret;
    }
};
  1. 首先,定义一个vector ret来存储结果,即符合条件的字母异位词的起始索引。
  2. 使用一个大小为26的数组hash1来记录字符串p中每个字符出现的次数。
  3. 使用两个大小为26的数组hash2和count来记录当前窗口中每个字符出现的次数和符合条件的字符个数。
  4. 使用两个指针left和right来表示窗口的左右边界,初始时两个指针都指向字符串s的第一个字符。
  5. 在循环中,右指针right向右移动,将当前字符加入到hash2中,并增加其出现次数。
  6. 如果hash2中当前字符的出现次数不超过hash1中的出现次数,说明当前字符是符合条件的字符,将count加1。
  7. 如果窗口的长度超过了字符串p的长度,需要移动左指针left来缩小窗口。
  8. 移动左指针时,将左边界对应的字符从hash2中减少出现次数,并判断减少后的次数是否小于等于hash1中的次数,如果小于等于,则说明减少后的字符不再符合条件,将count减1。
  9. 不断移动左指针,直到窗口的长度等于字符串p的长度。
  10. 在每次移动左指针后,判断count是否等于字符串p的长度,如果等于,则说明窗口中包含了一个字母异位词,将左指针的索引加入到结果数组ret中。
  11. 最后返回ret,即为所有符合条件的字母异位词的起始索引。

7、30. 串联所有单词的子串

思路:滑动窗口+哈希表

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(), slen = 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) {
                string in = s.substr(right, len);
                hash2[in]++;
                if (hash1.count(in) && hash2[in] <= hash1[in]) {
                    count++;
                }
                if (right - left + 1 > len * slen) {
                    string out = s.substr(left, len);
                    if (hash1.count(out) && hash2[out] <= hash1[out]) {
                        count--;
                    }
                    hash2[out]--;
                    left += len;
                }
                if (count == slen) {
                    ret.push_back(left);
                }
            }
        }
        return ret;
    }
};
  1. 首先,使用一个unordered_map(哈希表)hash1来记录words中每个字符串出现的次数。
  2. 然后,定义一个vector ret来存储结果,即符合条件的子串的起始索引。
  3. 接下来,通过两层循环来遍历s中的所有可能的子串。外层循环是根据words中字符串的长度来确定的,内层循环是遍历s中的每个字符。
  4. 在内层循环中,首先使用substr函数从s中截取长度为len的子串in,并将其加入到另一个unordered_map(哈希表)hash2中,并增加其出现次数。
  5. 然后,判断in是否在hash1中出现,并且hash2中的出现次数不超过hash1中的出现次数,如果满足条件,则将count加1。
  6. 接着,判断当前子串的长度是否超过了words中所有字符串的总长度,如果超过了,则需要移动左边界,即将左边界对应的子串从hash2中移除,并更新count的值。
  7. 最后,判断count是否等于words中字符串的个数,如果等于,则说明当前子串包含了words中所有字符串,将左边界的索引加入到ret中。
  8. 最后返回ret,即为所有符合条件的子串的起始索引。

8、76. 最小覆盖子串

思路:滑动窗口+哈希表

class Solution {
public:
    string minWindow(string s, string t) {
        int hash1[128] = {0}, kinds = 0;
        for (auto s : t) {
            if (hash1[s]++ == 0) {
                kinds++;
            }
        }
        int hash2[128] = {0}, count = 0, minlen = INT_MAX, begin = -1;
        for (int left = 0, right = 0; right < s.size(); right++) {
            char in = s[right];
            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--;
                }
            }
        }
        if (begin == -1) {
            return "";
        } else {
            return s.substr(begin, minlen);
        }
    }
};
  1. 首先,使用一个大小为128的数组hash1来记录字符串t中每个字符出现的次数,并使用一个变量kinds来记录不同字符的种类数。
  2. 使用两个大小为128的数组hash2和count来记录当前窗口中每个字符出现的次数和符合条件的字符种类数。
  3. 使用两个指针left和right来表示窗口的左右边界,初始时两个指针都指向字符串s的第一个字符。
  4. 在循环中,右指针right向右移动,将当前字符加入到hash2中,并增加其出现次数。
  5. 如果hash2中当前字符的出现次数等于hash1中的出现次数,说明当前字符是符合条件的字符,将count加1。
  6. 如果窗口中包含了字符串t中的所有字符,即count等于kinds,进入内层循环。
  7. 在内层循环中,首先判断当前窗口的长度是否小于最小窗口长度minlen,如果是,则更新minlen和begin的值。
  8. 然后,移动左指针left来缩小窗口,将左边界对应的字符从hash2中减少出现次数,并判断减少后的次数是否等于hash1中的次数,如果是,则说明减少后的字符不再符合条件,将count减1。
  9. 不断移动左指针,直到窗口中不再包含字符串t中的所有字符。
  10. 在每次移动左指针后,继续移动右指针来扩大窗口,重复步骤4-9,直到右指针到达字符串s的末尾。
  11. 最后,判断begin的值是否为初始值-1,如果是,则说明没有找到符合条件的窗口,返回空字符串;否则,根据begin和minlen截取最小窗口子串,并返回。

​ 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/358948.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

存储监控工具:监控存储区域网络(SAN)

从托管应用程序到提供大型多媒体服务&#xff0c;组织都依靠其 IT 基础架构来提供无与伦比的最终用户体验。为了提供这种卓越的体验&#xff0c;必须大大提高应用程序的可用性和性能。在许多其他挑战中&#xff0c;存储区域网络 &#xff08;SAN&#xff09; 正好用于应对这些挑…

TPCC-MySQL

简介 TPC-C是专门针对联机交易处理系统&#xff08;OLTP系统&#xff09;的规范&#xff0c;一般情况下我们也把这类系统称为业务处理系统。 Tpcc-mysql是percona基于TPC-C(下面简写成TPCC)衍生出来的产品&#xff0c;专用于MySQL基准测试。其源码放在launchpad上&#xff0c…

使用xlsx、xlsx-style导出表格添加背景色;合并单元格部分样式缺失问题解决

这篇说一下使用xlsx-style导出excel时样式的设置。需要安装xlsx、xlsx-style、file-saver插件&#xff08;file-saver可以不装&#xff0c;用a标签代替也可以&#xff09;&#xff0c;安装时可能会碰到一些报错问题&#xff0c;可以去看下我之前一篇博客&#xff1a;纯前端导出…

C语言之刷到的怪题(i与sizeof(i)比较大小)

这个题目一般都是选择输出<。为什么呢&#xff1f;因为i是一个全局变量&#xff0c;并且没有初始化&#xff0c;那么i的值就等于0。i--之后就是-1了。而sizeof(i)求出的就是整形变量对应的大小4个字节。-1<4&#xff0c;因此就选择 输出<。其实不然&#xff0c;这个si…

QEMU - e1000全虚拟化前端与TAP/TUN后端流程简析

目录 1. Host -> Guest 2.Guest ->Host 3. 如何修改以支持TUN设备的后端&#xff1f; 4. 相关 QEMU 源码 5. 实验 1. Host -> Guest 2.Guest ->Host 3. 如何修改以支持TUN设备的后端&#xff1f; 1. 简单通过后端网卡名字来判断是TUN还是TAP。 2. 需要前端全…

秋招面试—CSS篇

2021 CSS面试题 1.CSS可继承属性有哪些&#xff1f; 文字相关&#xff1a;font-famliy 、font-weight 、font-size 、font-style文本相关&#xff1a;text-indent&#xff08;首行缩进&#xff09; 、text-align&#xff08;水平对齐&#xff09; 、line-height 、text-trans…

node.js基础--01

Author nodes&#xff1a;&#xff08;题记&#xff09; node.js is an open-source&#xff0c;cross-platform JAVAScript runtime environment。 node.js是一个开源&#xff0c;跨平台的js运行环境 common commands&#xff08;常用指令&#xff09; 1、C: enter hard …

C# 一个快速读取写入操作execl的方法封装

这里封装了3个实用类ExcelDataReaderExtensions&#xff0c;ExcelDataSetConfiguration&#xff0c;ExcelDataTableConfiguration和一个实用代码参考&#xff1a; using ExcelDataReader; using System; using System.Collections.Generic; using System.Linq; using System.T…

解剖 Python 代码,深入学习 interpret 库的功能和应用!

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com Python是一门广泛应用的编程语言&#xff0c;拥有丰富的标准库和第三方库&#xff0c;可以用于各种应用场景。在Python中&#xff0c;有一个名为interpret的库&#xff0c;它提供了一种强大的方式来处理和执行Py…

一个通过下标查找数值的面试题解法

最近看到一道面试题&#xff0c;面试官说是算法题。我粗略看了下&#xff0c;努力在其中寻找数学公式&#xff0c;但是最后发现它算是一个数据结构相关的题目&#xff0c;没有算法层面的知识。 // There is an array generated by a rule. // The first item is 1. If k is in …

Codeforces Round 918 (Div. 4) 解题报告 | 珂学家 | 偏序 + 扩展Dijkstra

前言 整体评价 属于VP&#xff0c;感觉还是能AK的&#xff0c;E是偏序题&#xff0c;F是改版的迪杰特斯拉。 A. Odd One Out 题型: 签到 t int(input())for i in range(t):a, b, c list(map(int, input().split()))if a b:print (c)elif a c:print (b)else:print (a)B. …

基于Python的全国主要城市天气数据可视化大屏系统

1 绪论 1.1 研究的目的与意义 近年来&#xff0c;气候变化引发全球范围内的关注。天气数据的采集和分析对于气候预测、生态环境保护等方面都起着至关重要的作用。同时&#xff0c;随着科技的不断发展&#xff0c;数据可视化已经成为了许多领域中不可或缺的一部分。基于此&…

防御保护 笔记整理

一、ASPF--- 针对应用层的包过滤 ASPF --- 针对应用层的包过滤 --- 用来抓取多通道协议中协商端口的关键数据包&#xff0c;之后&#xff0c;将端 口算出&#xff0c;将结果记录在sever-map表中&#xff0c;相当于开辟了一条隐形的通道。 FTP --- 文件传输协议 FTP协议是一个典…

指针进阶1

一&#xff0c;字符指针 顾名思义&#xff1a;字符指针指的是一种指针类型为字符指针 char*&#xff1b; char*可以是一个字符也可以是一个字符串&#xff0c;前者很好理解&#xff0c;让我们看看后者&#xff1b; eg&#xff1a;char*p"abcdef";//实际上是将首元…

【开源精选导航】GitHub-Chinese-Top-Charts:一榜在手,优质中文项目轻松找寻

各位热爱开源技术的朋友们&#xff0c;你们是否有过这样的困扰&#xff1a;面对浩瀚的GitHub海洋&#xff0c;想找寻那些具有高质量中文文档的优秀开源项目却无从下手&#xff1f;今天&#xff0c;我们就为大家揭晓一个宝藏般的开源项目——GitHub 中文项目集合&#xff08;访问…

如何在win系统部署Apache服务并实现无公网ip远程访问

文章目录 前言1.Apache服务安装配置1.1 进入官网下载安装包1.2 Apache服务配置 2.安装cpolar内网穿透2.1 注册cpolar账号2.2 下载cpolar客户端 3. 获取远程桌面公网地址3.1 登录cpolar web ui管理界面3.2 创建公网地址 4. 固定公网地址 前言 Apache作为全球使用较高的Web服务器…

idea项目如何上传gitee

1.先创建仓库 2.从gitee上面clone下来 3.配置一下git 4.在idea里面安装Gitee插件&#xff08;安装完插件重启一下&#xff09; 5.将项目提交到远程仓库 git->add->✔ 完后点击↗ 在码云如何获取token&#xff1f; 注&#xff1a;没有解决&#xff0c;有时间在继续研究

linux kernel 内存踩踏之KASAN(一)

一、背景 linux 内核出现内存类问题时&#xff0c;我们常用的调试工具就是kasan&#xff0c;kasan有三种模式&#xff1a; 1. Generic KASAN &#xff08;这个就是我们最常用的&#xff0c;1 debug byte indicate 8 bytes use state, 对标用户层 asan&#xff09; 2. Softwa…

滴滴举行网约车合作伙伴大会,与174家合作伙伴共商发展

近日&#xff0c;滴滴在昆明举行主题为“凝心聚力&#xff0c;共享发展”的第四届网约车合作伙伴大会&#xff0c;汽车租赁公司、司机服务公司、主机厂、金融机构等174家上下游生态链合作伙伴齐聚一堂。滴滴已连续四年举办网约车合作伙伴大会&#xff0c;邀请合作伙伴广泛参与、…

机器学习 | 掌握 K-近邻算法 的理论实现和调优技巧

目录 初识K-近邻算法 距离度量 K值选择 kd树 数据集划分 特征预处理 莺尾花种类预测(实操) 交叉验证与网格搜索 初识K-近邻算法 K-近邻算法&#xff08;K-Nearest Neighbor&#xff0c;KNN&#xff09;是一种基本的分类和回归算法。它的基本思想是通过找出与新对象最近…
最新文章