coding ability 展开第三幕(滑动指针——基础篇)超详细!!!!

news2025/3/14 8:43:56

在这里插入图片描述

文章目录

  • 前言
  • 滑动窗口
  • 长度最小的子数组
    • 思路
  • 无重复字符的最长子串
    • 思路
  • 最大连续1的个数
    • 思路
  • 将x减到0的最小操作数
    • 思路
  • 总结

前言

前面我们已经把双指针的一些习题练习的差不多啦
今天我们来学习新的算法知识——滑动窗口
让我们一起来探索滑动窗口的魅力吧

滑动窗口

滑动窗口算法(Sliding Window Algorithm)是一种用于处理数组、字符串等线性数据结构的高效算法。它通过维护一个动态的窗口来优化计算过程滑动窗口的核心思想是通过逐步移动窗口来获得所需的结果,而不是每次都从头开始重新计算。这个方法能够减少时间复杂度,从而提高算法效率。

滑动窗口算法的基本思想
滑动窗口算法分为两个主要类型:
1.固定大小窗口(Fixed-size Sliding Window):窗口的大小在整个过程中保持不变。
2.可变大小窗口(Variable-size Sliding Window):窗口的大小可以根据需求变化,通常是通过扩展或收缩窗口来满足特定条件。
滑动窗口的工作原理
1.初始化窗口:在数据结构的开始处创建一个窗口,并根据问题的需要选择适当的大小。
2.移动窗口:窗口通常从左到右(或其他方向)滑动每次滑动时,更新窗口内的信息
3.计算或更新结果:每次移动窗口时,计算窗口内的相关信息,通常是某种聚合值(如求和、最大值等)。

滑动窗口的应用场景
滑动窗口算法常用于以下几种常见问题中:
1.最大子数组和问题:给定一个整数数组,找到其所有连续子数组的和的最大值。
2.无重复字符的最长子串:给定一个字符串,找到其中没有重复字符的最长子串的长度。
3.最小覆盖子串:给定一个字符串和一个字符集合,找到覆盖所有字符的最小子串。
4.固定大小子数组的滑动:找到所有固定大小的子数组中,和最大的子数组。

实践是检验真理的唯一标准,一起来刷题吧

长度最小的子数组

在这里插入图片描述

思路

首先想到的肯定是暴力解法:
「从前往后」枚举数组中的任意一个元素,把它当成起始位置。然后从这个「起始位置」开始,然后寻找一段最短的区间,使得这段区间的和「大于等于」目标值。将所有元素作为起始位置所得的结果中,找到「最小值」即可
不用多说,超时是必然的。
这题分析的对象时一段连续的区间,由此我们想到可以试试滑动窗口来解决
让滑动窗口满足:从 i 位置开始窗口内所有元素的和小于 target那么当窗口内元素之和第一次大于等于目标值的时候,就是 i 位置开始,满足条件的最小长度
每一次将右端元素划入窗口,然后统计出窗口内元素和
如果窗口内元素和小于 target,那就 right++,继续将右边元素划入窗口
如果窗口内元素和大于等于target,那就更新结果,并且将左端元素划去窗口,同时判断是否满足条件并更新结果,直到小于target

话不多说上代码吧

class Solution 
{
public:
    int minSubArrayLen(int target, vector<int>& nums) 
    {
        int n = nums.size(), ans = INT_MAX;
        int sum = 0;
        for(int left = 0, right = 0; right < n; right++)
        {
            sum += nums[right];   //  右端元素划入窗口
            while(sum >= target)   
            {
                ans = min(ans, right - left + 1);  //  满足条件更新结果
                sum -= nums[left];
                left++;
            }
        }
        return ans == INT_MAX ? 0 : ans;  
    }
};

无重复字符的最长子串

在这里插入图片描述

思路

第一种还是暴力解法,试了一试,发现能过
思路就是每到一个位置,就遍历到无重复子串能到什么位置,找出最大长度就行
怎么判断已经到了有重复字母的位置能,我们可以用哈希表来计数,统计频次,频次大于1就截止

代码如下:

class Solution 
{
public:
	int lengthOfLongestSubstring(string s) 
	{
		int ret = 0; // 记录结果
		int n = s.length();
		// 1. 枚举从不同位置开始的最长重复子串
		// 枚举起始位置
		for (int i = 0; i < n; i++)
		{
			// 创建一个哈希表,统计频次
			int hash[128] = { 0 };
			// 寻找结束为止
			for (int j = i; j < n; j++)
			{
				hash[s[j]]++; // 统计字符出现的频次
				if (hash[s[j]] > 1) // 如果出现重复的
				break;
				// 如果没有重复,就更新 ret
				ret = max(ret, j - i + 1);
			}
		}
		// 2. 返回结果
		return ret;
	}
};

第二种解法就是滑动窗口了
想到这里是一段连续的区间,我们可以使用滑动窗口来优化
让窗口满足所有元素都不相同,右端字符不断进入窗口,然后用哈希统计频次,一旦频次有大于 1 的 就从左边划出窗口,直到这个字符频次等于1,再更新结果
如果没有大于1的频次的字符,就一直更新结果就好啦

代码如下:

class Solution 
{
public:
    int lengthOfLongestSubstring(string s) 
    {
        int hash[128] = {0};  // 使用数组模拟哈希
        int right = 0, left = 0, n = s.size();
        int ans = 0;
        while(right < n)
        {
            hash[s[right]]++;   //  进窗口
            while(hash[s[right]] > 1)  //  维护窗口
            {
                hash[s[left++]]--;
            }
            ans = max(ans, right - left + 1);//  更新结果
            right++;  //  下一个元素进窗口
        }
        return ans;
    }
};

最大连续1的个数

在这里插入图片描述

思路

粗看不知道怎么处理,细看想想有个k
那不就是一段连续的 1 区间塞进去 k 个 0,我们可以把问题转化成:
求一段最长的连续区间,要求这段区间内的 0 的个数不超过 k 个,连续区间问题就来到了我们的滑动窗口
流程:
right一直向右遍历,如果等于0 就进窗口,k–,每次判断 k是否小于0,如果小于 0 就处理左边left,直到 k 大于等于 0 ,同时更新结果

代码如下:

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

将x减到0的最小操作数

在这里插入图片描述

思路

题目要求的是 左右 两端 连续的和为x的最短数组,处理起来相对比较麻烦,我们不如反过来看,数组和为sum,sum - x就是剩下中间连续数组的和,那我们就可以把原来的问题转化成:
一段和为sum - x的最长连续子数组,又来到我们的滑动窗口啦

转化问题:求 target = sum(nums) - x 。如果 target < 0 ,问题无解
b. 初始化左右指针 l = 0 , r = 0 (滑动窗口区间表示为 [l, r) ,左右区间是否开闭很重要,必须设定与代码一致),记录当前滑动窗口内数组和的变量 sum = 0 ,记录当前满足条件数组的最大区间长度 maxLen = -1
c. 当r 小于等于数组长度时,一直循环
i. 如果 sum < target ,右移右指针,直至变量和大于等于 target ,或右指针已经移到头;
ii. 如果 sum > target ,右移左指针,直至变量和小于等于 target ,或左指针已经移到头;
iii. 如果经过前两步的左右移动使得 sum == target ,维护满足条件数组的最大长度,并让下个元素进入窗口
d. 循环结束后,如果 maxLen 的值有意义,则计算结果返回;否则,返回-1

代码如下:

class Solution
{
public:
	int minOperations(vector<int>& nums, int x)
	{
		int sum = 0;
		for(int a : nums) sum += a;
		int target = sum - x;
		// 细节问题
		if(target < 0) return -1;  //  这里就代表整个数组都小于 x 
		int ret = -1;
		for(int left = 0, right = 0, tmp = 0; right < nums.size(); right++)
		{
			tmp += nums[right]; // 进窗口
			while(tmp > target) // 维护窗口
			tmp -= nums[left++]; 
			if(tmp == target) 
			ret = max(ret, right - left + 1);// 更新结果
		}
		if(ret == -1) return ret;
		else return nums.size() - ret;
	}
};

总结

通过四个有关滑动窗口的题目,让我深有体会
主要就是抓住了核心——一段连续的区间
然后对连续的区间进行维护以及处理,滑动窗口在处理连续区间问题还是非常好用的
今天的学习就到这里啦
不要走开,小遍持续更新中~~~~~

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何自己做奶茶,从此告别奶茶店

自制大白兔奶茶&#xff0c;奶香与茶香激情碰撞&#xff0c;每一口都是香浓与甜蜜的双重诱惑&#xff0c;好喝到跺脚&#xff01;丝滑口感在舌尖舞动&#xff0c;仿佛味蕾在开派对。 简单几步就能复刻&#xff0c;成本超低&#xff0c;轻松在家享受奶茶自由。 材料:大白兔奶糖&…

宇树人形机器人开源模型

1. 下载源码 https://github.com/unitreerobotics/unitree_ros.git2. 启动Gazebo roslaunch h1_description gazebo.launch3. 仿真效果 H1 GO2 B2 Laikago Z1 4. VMware: vmw_ioctl_command error Invalid argument 这个错误通常出现在虚拟机环境中运行需要OpenGL支持的应用…

【Linux】浅谈冯诺依曼和进程

一、冯诺依曼体系结构 冯诺依曼由 输入设备、输出设备、运算器、控制器、存储器 五部分组成。 冯诺依曼的设计特点 二进制表示 所有数据&#xff08;包括程序指令&#xff09;均以二进制形式存储和运算&#xff0c;简化了硬件逻辑设计&#xff0c;提高了可靠性。 存储程序原理…

linux操作系统实战

第一题 创建根目录结构中的所有的普通文件 [rootlocalhost ~]# cd /[rootlocalhost /]# mkdir /text[rootlocalhost /]# cd /text[rootlocalhost text]# mkdir /text/boot /text/root /text/home /text/bin /text/sbin /text/lib /text/lib64 /text/usr /text/opt /text/etc /…

浅谈时钟启动和Systemlnit函数

时钟是STM32的关键&#xff0c;是整个系统的心脏&#xff0c;时钟如何启动&#xff0c;时钟源如何选择&#xff0c;各个参数如何设置&#xff0c;我们从源码来简单分析一下时钟的启动函数Systemlnit&#xff08;&#xff09;。 Systemlnit函数简介 我们先来看一下源程序的注释…

MySql学习_基础Sql语句

目录 1.数据库相关概念 2.SQL 2.1 SQL通用语法 2.2 SQL分类 2.3 DDL&#xff08;数据库定义语言&#xff09; 2.4 DML&#xff08;数据操作语言&#xff09; 2.5 DQL&#xff08;数据查询语言&#xff09; 2.6 DCL&#xff08;数据控制语言&#xff09; 3. 函数 3.1 字…

小白学Agent技术[5](Agent框架)

文章目录 Agent框架Single Agent框架BabyAGIAutoGPTHuggingGPTHuggingGPT工作原理说明GPT-EngineerAppAgentOS-Copilot Multi-Agent框架斯坦福虚拟小镇TaskWeaverMetaGPT微软UFOAgentScope现状 常见Agent项目比较概述技术规格和能力实际应用案例开发体验比较ChatChain模式 Agen…

VSTO(C#)Excel开发4:打印设置

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github&#xff1a;codetoys&#xff0c;所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的&#xff0c;可以在任何平台上使用。 源码指引&#xff1a;github源…

设计模式Python版 模板方法模式(上)

文章目录 前言一、模板方法模式二、模板方法模式示例 前言 GOF设计模式分三大类&#xff1a; 创建型模式&#xff1a;关注对象的创建过程&#xff0c;包括单例模式、简单工厂模式、工厂方法模式、抽象工厂模式、原型模式和建造者模式。结构型模式&#xff1a;关注类和对象之间…

transformer bert 多头自注意力

输入的&#xff08;a1,a2,a3,a4&#xff09;是最终嵌入&#xff0c;是一个(512,768)的矩阵&#xff1b;而a1是一个token&#xff0c;尺寸是768 a1通过wq权重矩阵&#xff0c;经过全连接变换得到查询向量q1&#xff1b;a2通过Wk权重矩阵得到键向量k2&#xff1b;q和k点乘就是值…

python-leetcode-定长子串中元音的最大数目

1456. 定长子串中元音的最大数目 - 力扣&#xff08;LeetCode&#xff09; 可以使用 滑动窗口 方法来解决这个问题。步骤如下&#xff1a; 初始化&#xff1a;计算前 k 个字符中元音字母的个数&#xff0c;作为初始窗口的值。滑动窗口&#xff1a;遍历字符串&#xff0c;每次右…

MySQL增删改查操作 -- CRUD

个人主页&#xff1a;顾漂亮 目录 1.CRUD简介 2.Create新增 使用示例&#xff1a; 注意点&#xff1a; 3.Retrieve检索 使用示例&#xff1a; 注意点&#xff1a; 4.where条件查询 前置知识&#xff1a;-- 运算符 比较运算符 使用示例&#xff1a; 注意点&#xf…

【算法day9】回文数-给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。

回文数 给你一个整数 x &#xff0c;如果 x 是一个回文整数&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 回文数是指正序&#xff08;从左向右&#xff09;和倒序&#xff08;从右向左&#xff09;读都是一样的整数。 例如&#xff0c;121 是回文&#…

蛋白质功能预测论文阅读记录2025(DPFunc、ProtCLIP)

前言 最近研究到瓶颈了&#xff0c;怎么优化都提升不了&#xff0c;遂开始看点最新的论文。 DPFunc 2025.1.2 Nature Communication 中南大学 论文地址&#xff1a;DPFunc: accurately predicting protein function via deep learning with domain-guided structure inform…

主流向量数据库对比

在 AI 的 RAG&#xff08;检索增强生成&#xff09;研发领域&#xff0c;向量数据库是存储和查询向量嵌入的核心工具&#xff0c;用于支持高效的语义搜索和信息检索。向量嵌入是文本或其他非结构化数据的数值表示&#xff0c;RAG 系统通过这些嵌入从知识库中检索相关信息&#…

54.HarmonyOS NEXT 登录模块开发教程(八):测试与调试技巧

温馨提示&#xff1a;本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦&#xff01; HarmonyOS NEXT 登录模块开发教程&#xff08;八&#xff09;&#xff1a;测试与调试技巧 文章目录 HarmonyOS NEXT 登录模块开发教程&#xff08;…

在Simulink中将Excel数据导入可变负载模块的方法介绍

文章目录 数据准备与格式要求Excel数据格式MATLAB预处理数据导入方法使用From Spreadsheet模块(直接导入Excel)通过MATLAB工作区中转(From Workspace模块)使用1-D Lookup Table模块(非线性负载映射)Signal Builder模块(变载工况导入)可变负载模块配置注意事项与调试在S…

动手学强化学习-记录

3.5 蒙特卡洛方法 统计每一个状态s出现的总次数和总回报&#xff0c;用大数定律&#xff0c;总回报/总次数≈状态s的期望回报 第4章 动态规划算法 策略迭代中的策略评估使用贝尔曼期望方程来得到一个策略的状态价值函数,这是一个动 态规划的过程;而价值迭代直接使用贝尔曼最…

阿里云操作系统控制台评测:国产AI+运维 一站式运维管理平台

阿里云操作系统控制台评测&#xff1a;国产AI运维 一站式运维管理平台 引言 随着云计算技术的飞速发展&#xff0c;企业在云端的运维管理面临更高的要求。阿里云操作系统控制台作为一款集运维管理、智能助手和系统诊断等多功能于一体的工具&#xff0c;正逐步成为企业高效管理…

C++中的const与类型转换艺术

目录 强制转换 static_cast const_cast reinterpret_cast dynamic_cast const关键字 修饰内置类型* 修饰指针类型* 类比 数组指针 指针数组 函数指针 指针函数 强制转换 C语言中的强制转换在C代码中依然可以使用&#xff0c;这种C风格的转换格式非常简单 TYPE a …