定长滑动窗口--灵神题单(一刷进阶)

简介: 这篇文章主要围绕灵神题单中的定长滑动窗口进阶题进行探讨,首先解决了一些基本题目,然后附带了一些相对困难题目的解题思路。值得注意的是,大部分解答都是在前人的基础上进行了一些小的修改和调整。希望文章对大家的学习和解题能力有所帮助。如果您需要更具体的内容或者对某一部分有兴趣深入讨论,请告诉我!


目录

第一题:2134. 最少交换次数来组合所有的 1 II - 力扣(LeetCode)

按照力扣的 滑动窗口 标签刷到这题,知道是滑窗,但想了半天没想到怎么滑。
再看了下灵神给的滑动窗口题单【题单】滑动窗口(定长/不定长/多指针) 里面把这题归类为定长滑动窗口。
说是定长滑窗。那只能是 1的总数 或 0的总数 当作固定的窗口长度吧。
那就两种情况都写一下,反正都是O(n)。
窗口长度固定为0的总数,那窗口内 要被替换成0的个数,即窗口内1的个数就是结果,求最小
窗口长度固定为1的总数,那窗口内 要被替换成1的个数,即窗口内0的个数就是结果,求最小
上述两个结果都求出来,然后再求个最小,然后就通过了。
定长滑窗的具体写法是 初始窗口处理好,然后右端进一个,左端出一个。
class Solution {
public:
int minSwaps(vector& nums) {
int n = nums.size();
int count_1 = 0;// 统计一的个数
for (auto& num : nums) count_1 += num;
int count_0 = n - count_1;
int ret = n;
for (int left = 0, right = 0, count = 0; right < n; right++)
{
// 进窗口
count += nums[right];
// 判断
if (right - left + 1 >= count_1)
{
ret = min(ret, count_1 - count);
count -= nums[left++];
}
}
for (int left = 0, right = 0, count = 0; right < n; right++)
{
// 进窗口
if (nums[right] == 0)
{
count += 1;
}
// 判断
if (right - left + 1 >= count_0)
{
ret = min(ret, count_0 - count);
if (nums[left++] == 0) count -= 1;
}
}
return ret;
}
};
第二题:567. 字符串的排列 - 力扣(LeetCode)

这一道题如果想到要去使用哈希表,其实是非常的简单的,最主要的是如何想办法去优化。

检查字符串s2是否包含s1的排列。你通过hash1记录s1中每个字符的频率,并通过hash2跟踪当前窗口内字符的频率。每次滑动窗口时,更新字符的计数并检查是否满足s1的字符频率。优化点在于:1. 通过滑动窗口避免重复遍历,

  1. 只对s1中出现的字符进行操作,减少不必要的计算。通过count变量追踪窗口中字符的匹配数量,避免了每次都重新计算。

class Solution {
public:
bool checkInclusion(string s1, string s2) {
int n1 = s1.size();
int n2 = s2.size();
if (n1 > n2)
return false; // 如果s1的长度大于s2,直接返回false
unordered_map hash1;
for (auto& e : s1)
hash1[e]++;
unordered_map hash2;
for (int left = 0, right = 0, count = 0; right < n2; right++) {
// 进窗口
char in = s2[right];
if (hash1.find(in) != hash1.end()) {
hash2[in]++;
if (hash2[in] <= hash1[in])
count++;
}
// 判断 出
if (right - left + 1 >= n1)
{
if (count == n1)
{
return true;
}
char ou = s2[left++];
if (hash1.find(ou) != hash1.end())
{
// 如果移出的字符在 s1 中出现过,更新 hash2 和 count
if (hash2[ou] <= hash1[ou])
{
count--;
}
hash2[ou]--;
}
}
}
return false;
}
};
第三题:438. 找到字符串中所有字母异位词 - 力扣(LeetCode)

这一道题其实也是非常简单的定长滑动窗口。没什么难度。就不解释了,直接给代码吧。

但是还是要给出疑问:

使用哈希表好?还是数组好? 给出为什么?

class Solution {
public:
vector findAnagrams(string s, string p) {
int hash1[26]={0};
int m=p.size();
for(auto& e:p) hash1[e-'a']++;
int hash2[26]={0};
int n=s.size();
vector ret;
for(int left=0,right=0,count=0;rightm )
{
if(hash2[ou-'a']--<=hash1[ou-'a']) count--;
left++;
}
//更新结果
if(count==m)
{
ret.push_back(left);
}
}
return ret;
}
};
第四题:2156. 查找给定哈希值的子串 - 力扣(LeetCode)

这一道题其实也是不是很难,虽然力扣给出是困难题,但是只要了解一些数学知识,把题目的过程简化,难度连中等题都谈不上。

但这一切前提都是你对该部分数学知识了解,如果不了解,根本无思路。

推荐文章:分享丨模运算的世界:当加减乘除遇上取模(模运算恒等式/费马小定理) - 力扣(LeetCode)

代码:

class Solution {
public:
string subStrHash(string s, int power, int modulo, int k, int hashValue) {
int n=s.size();
string ret;
int h = 0; // 子串哈希值
for(int left=0,right=0;right=k)
{
if(h==hashValue)
{
ret=s.substr(left,k);
}
// 出
if(h==0) h=modulo;
h=(long long)h-(s[left++]-'a'+1)* power % modulo;
}
}
return ret;
}
};
第五题:1016. 子串能表示从 1 到 N 数字的二进制串 - 力扣(LeetCode)
看到这一题的时候我也是一头雾水,但是看过灵神写的题解,才慢慢反应过来。

灵神首先给出的是暴力求解

对于方法一,其实我开始也看不明白代码什么意思

class Solution {
public:
bool queryString(string s, int n) {
for(int i=1;i<=n;i++)
{
auto bin = bitset<32>(i).to_string();
bin = bin.substr(bin.find('1'));
if(s.find(bin) == -1) return false;
}
return true;
}
};
这里使用gtp解释一下

对于方法二:

直接截图看灵神的解释吧,人家写的太详细了,想的太妙了,尤其是其中的(x << 1) | (c - '0')。

但是妙归妙,还是要看完思路,自己尝试首先一下代码。

class Solution {
public:
bool queryString(string s, int n) {
unordered_set ans;
for(int i=0,m=s.size();i<m;i++)
{
int x=s[i]-'0';
if(x==0) continue;// 二进制为,继续
for(int j=i+1;x<=n;j++)
{
ans.insert(x);
if(j==m) break;
x=(x<<1) | (s[j]-'0');
}
}
return ans.size()==n;
}
};
第六题:2269. 找到一个数字的 K 美丽值 - 力扣(LeetCode)

这道题要说它简答吧,直接暴力硬写也可以写出来,但是要说它简单,但要使用滑动窗口来写,又比较麻烦。

思路好想,没什么难度,直接给代码

class Solution {
public:
int divisorSubstrings(int num, int k) {
vector v; //存放num这个数串每个位的值
int n; //代表数串每个位数的值
int num1 = num; //将num赋给num1
int res = 0;//美丽值-返回的结果
while(num1 != 0){//从个位 十位 百位...依次压入v容器中
n = num1%10;//余数
num1 = num1/10;//自除更新num1
v.push_back(n);
}
reverse(v.begin(),v.end());//逆序v容器的元素
int left = 0;//左边界
int right = k-1;//右边界 //0到k-1正好k个数
for(left,right;right<v.size();right++,left++){//滑动窗口方式模拟验证
int tmp = v[left];//初始化tmp 滑动窗口左边界代表 窗口内数串的最高位
for(int i=left+1;i<=right;i++){
tmp = tmp*10+v[i]; //模拟滑动窗口中元素组成一个数
}
if(tmp == 0)//如果为0,直接下一次循环
continue;
if(num%tmp == 0 ) {//如果可整除,美丽值结果+1
res++;
}
}
return res;//返回结果
}
};
第七题: 1984. 学生分数的最小差值 - 力扣(LeetCode)

如果是在没有思路,那不妨先让其有序。

class Solution {
public:
int minimumDifference(vector& nums, int k) {
int ret=INT_MAX;
int n=nums.size();
sort(nums.begin(),nums.end());
for(int left=0,right=0;right<n;right++)
{
if(right-left+1==k)
{
ret=min(ret,(nums[right]-nums[left++]));
}
}
return ret;
}
};
没有解决的题目:

会员题除外

  1. 统计完全子字符串 - 力扣(LeetCode)

  2. 使二进制字符串字符交替的最少反转次数 - 力扣(LeetCode)

  3. 存在重复元素 III - 力扣(LeetCode)

目录
相关文章
|
2月前
|
人工智能 数据可视化 测试技术
Coze平台指南(3):核心功能-创建智能体与设计角色
Coze 智能体是由大语言模型驱动,通过提示词设定角色,并借助知识库、插件和工作流扩展能力,以执行特定任务的AI助手。对测试工程师而言,精心设计的智能体可显著提升测试效率与质量,关键是要准确理解测试需求,并将其转化为智能体的角色设定和功能配置。建议进一步学习知识库与工作流,以深化应用。
|
Java Linux Shell
Docker centos7 中文乱问题解决方案
Docker centos7 中文乱问题解决方案
1034 0
|
9月前
|
自然语言处理 监控 安全
2025年阿里云短信验证码价格多少钱?计费模式与场景选型指南
随着企业数字化转型,短信验证码作为用户身份验证的重要工具,其成本与效率的平衡至关重要。阿里云短信服务以高可靠性、灵活计费和多场景适配著称。按量付费模式适合需求波动大的场景,而短信套餐包则为长期稳定需求提供了成本优势。针对不同业务场景,如高频验证、跨境业务及中小型企业轻量级需求,阿里云提供了定制化的选型策略。此外,通过阶梯定价、防盗刷监控等措施实现成本优化与风险规避,并不断进行技术升级以确保服务的安全性和稳定性。根据2025年最新数据,企业可根据自身需求选择最适合的阿里云短信验证码服务方案。
|
10月前
|
传感器 机器学习/深度学习 人工智能
智能电网巡检与传感器数据AI自动分析
智能电网设备巡检与传感器数据分析利用AI技术实现自动化分析和预警。通过信息抽取、OCR技术和机器学习,系统可高效处理巡检报告和实时数据,生成精准报告并提供故障预判和早期识别。AI系统24小时监控设备状态,实时发出异常警报,确保设备正常运行,提升运维效率和可靠性。
501 6
|
10月前
|
Java 关系型数据库 数据库连接
mybatis中的useGeneratedKeys和keyProperty
在 MyBatis 中,`useGeneratedKeys` 和 `keyProperty` 是用于处理数据库自动生成主键的关键配置。通过这些配置,可以方便地获取和使用数据库生成的主键值,提高开发效率和代码可读性。确保正确配置和使用这两个属性,可以在应用程序中高效地进行数据库操作。
398 25
|
监控 Cloud Native 持续交付
云原生架构:构建弹性与高效的现代应用##
随着云计算技术的不断成熟,云原生架构逐渐成为企业技术转型的重要方向。本文将深入探讨云原生的核心概念、主要技术和典型应用场景,以及如何通过云原生架构实现高可用性、弹性扩展和快速迭代,助力企业在数字化转型中保持竞争优势。 ##
504 6
|
安全 前端开发 Java
Spring Security是如何工作的?
Spring Security 是一个强大的框架,用于保护 Spring 应用程序,提供全面的安全服务,包括身份验证、授权等功能。本文将介绍其核心概念及默认配置。Spring Security 通过与 Spring MVC、Spring Webflux 或 Spring Boot 集成,创建高度可定制的身份验证和访问控制框架。其核心组件包括 Servlet Filters、Authentication 和 Authorization。通过默认的过滤器链和一系列预定义过滤器,Spring Security 可以轻松实现各种安全功能。
867 3
|
12月前
|
机器学习/深度学习 编解码 算法
在线打开CAD或Solidworks的STP文件,通过以图搜图与实物比对搜索
智能比对系统利用大模型技术,实现设计图纸与实物的高效、精准比对。系统支持在线3D模型解析、多视图图片自动生成、实物照片智能比对及实时偏差标注,全面提升机械制造行业的设计、生产和质量控制效率。
666 2
|
传感器 机器人 芯片
实例4:树莓派GPIO控制舵机转动
本文是关于使用树莓派GPIO控制舵机转动的实验教程,涵盖了舵机的基本概念、结构、工作原理以及PWM信号控制方法。实验目的是通过Python编程,实现树莓派控制舵机在0°~180°范围内周期性转动。文中提供了详细的实验步骤、代码示例以及舵机调零和校准的方法。
920 1
实例4:树莓派GPIO控制舵机转动
|
边缘计算 网络协议 5G