算法 —— 滑动窗口

news2024/12/27 17:20:25

目录

长度最小的子数组

无重复字符的最长子串 

最大连续1的个数

将x减到0的最小操作数

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


长度最小的子数组

sum比target小就进窗口,sum比target大就出窗口,由于数组是正数,所以相加会使sum变大,相减会使sum变小,至于为什么可以这样做,这其实是在暴力枚举的基础上进行了优化,例如2,3,1,2相加等于8已经超过target,这样就不需要继续加后面的4,3,因为此时已经满足条件,我们要做的是在满足要求的基础上使len尽量小。 

代码实现如下:

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int sum = 0, len = INT_MAX, n = nums.size();
        for (int right = 0, left = 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;
    }
};

无重复字符的最长子串 

利用哈希表记录字符个数,注意本题字符包括数字,字母及空格,意味着我们要开一个128大小的数组。代码实现如下:

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int hash[128] = { 0 }; // 使用数组来模拟哈希表
        int n = s.size(), len = 0;
        for (int left = 0, right = 0; right < n;right++)
        {
            hash[s[right]]++; // 进窗口
            while (hash[s[right]] == 2) // 判断
            {
                hash[s[left++]]--; // 出窗口
            }
            len = max(len, right - left + 1); // 更新结果
        }
        return len;
    }
};

最大连续1的个数

和上题类似,通过滑动窗口,调节0的个数,最关键的在于将题目意思转换为找不超过k个0的子数组,如果超过k就出窗口,未超过就进窗口,代码实现如下:

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--;
                left++; // 出窗口
            }
            len = max(len, right - left + 1);
        }
        return len;
    }
};

将x减到0的最小操作数

本题思想为正难则反,如果题目正向思考困难,可以从另外一方面思考,例如本题要找最短长度,且元素可能在左右端口出现,另外最短长度数组元素之和刚好为x,这个代码实现起来过于麻烦,可以想找一个最长长度的子数组,使他元素之和刚好为sum - x,这样又转化为滑动窗口问题。

注意:len不能设置为0,因为有可能整个数组都是构成x的元素,最终判断是否存在时不能用len == 0 这个判断式来判断数组是否存在子数组可以将x减到0,应当设置为-1。另外,该题只有在sum2 == target时才能更新结果,否则不更新。代码如下:

class Solution {
public:
    int minOperations(vector<int>& nums, int x) {
        // 记算整个数组的和
        int sum1 = 0, n = nums.size();
        for (auto e : nums)
        {
            sum1 += e;
        }
        // 找出最长子数组的和 sum1 - x
        int target = sum1 - x, len = -1, sum2 = 0;

        // 处理细节问题
        if (target < 0)
            return -1;

        // 滑动窗口解决问题
        for (int left = 0, right = 0; right < n; right++)
        {
            sum2 += nums[right]; // 进窗口

            while (sum2 > target) // 判断
                sum2 -= nums[left++]; // 出窗口

            if (sum2 == target)
                len = max(len, right - left + 1); // 更新结果
        }
        if (len == -1)
            return len;
        else
            return n - len;
    }
};

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

在更新结果时不需要遍历两个哈希表,通过count计数器来判断hash2里的有效个数是否和m相等即可,代码实现如下:

class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        int hash1[26] = { 0 }, hash2[26] = { 0 }, n = s.size(), m = p.size();
        // 统计 p 的每个字符出现的次数
        for (auto e : p)
            hash1[e - 'a']++;

        vector<int> ret;
        // 统计 s 的每个字符出现的次数
        for (int left = 0, right = 0,count = 0; right < n; right++)
        {
            char in = s[right];
            if (++hash2[in - 'a'] <= hash1[in - 'a']) // 进窗口 + 维护 count
                count++;
            if (right - left + 1 > m) // 判断
            {
                char out = s[left++];
                if (hash2[out - 'a']-- <= hash1[out - 'a']) // 出窗口 + 维护 count
                    count--;
            }

            // 更新结果
            if (count == m)
                ret.push_back(left);
        }
        return ret;
    }
};

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

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

相关文章

云计算与生成式AI的技术盛宴!亚马逊云科技深圳 Community Day 社区活动流程抢先知道!

小李哥最近要给大家分享7月7日在深圳的即将举办的亚马逊云科技生成式AI社区活动Community Day &#xff0c;干货很多内容非常硬核&#xff0c;不仅有技术分享学习前沿AI技术&#xff0c;大家在现场还可以动手实践沉浸式体验大模型&#xff0c;另外参与现场活动还可以领取诸多精…

高优先线程

你开发的时候有么有遇到过一个问题&#xff1a;服务器的一个服务线程过几个小时断连一次&#xff0c;断连之后会马上重连这种情况。这是由于CPU负载较高,线程调度时将处理数据的线程挂起了一段时间导致的。 因此&#xff0c;我有考虑到把cpu的核心进行分散开来&#xff0c;就类…

关于发那科机器人系统升级方法

首先需要镜像备份和全备份&#xff0c;最好把机器人要到刻度线位置&#xff0c;零点位置 选择控制器启动&#xff0c;也可以按preevnext进入控制器模式

技术革新:如何用数据中台实现数字化转型

作为程序员&#xff0c;我们总是对技术如何改变企业运作充满好奇。今天&#xff0c;我们将深入探讨森马集团如何利用数据中台技术&#xff0c;实现从传统数据分析到数字化转型的华丽转身。 1. 技术背景&#xff1a;森马集团的数字化挑战 森马集团&#xff0c;一个在服饰行业占…

幻兽帕鲁服务器如何安装模组安装

由于模组多数为Window版本的&#xff0c;所以本教程以服务端为Window的作为演示&#xff08;Linux服务端的也是一样的操作&#xff09;百度莱卡云开服 如果你你是Linux版本的&#xff0c;请点击跳转切换服务端教程 接下来是本地安装模组包的方法&#xff08;服务器自带&#xf…

浅谈定时器之同步定时器

浅谈定时器之同步定时器 “同步定时器”&#xff08;Synchronizing Timer&#xff09;是一个特别的定时器&#xff0c;它用于确保在特定时间点上多个线程&#xff08;或虚拟用户&#xff09;同时发起请求&#xff0c;这对于测试系统在高并发情况下的表现尤为重要。本文将深入解…

通义灵码 Visual Studio 小白上手指南

一、下载和安装指南 本安装步骤适用于 Windows 10 及以上操作系统中安装和使用通义灵码。 步骤 1&#xff1a;准备工作 操作系统&#xff1a;Windows 10 及以上&#xff1b;下载并安装 ****Visual Studio 2022 17.3.0 及以上版本。 步骤 2&#xff1a;在 Visual Studio 202…

【Linux】:命令行参数

朋友们、伙计们&#xff0c;我们又见面了&#xff0c;本期来给大家解读一下有关Linux命令行参数的相关知识点&#xff0c;如果看完之后对你有一定的启发&#xff0c;那么请留下你的三连&#xff0c;祝大家心想事成&#xff01; C 语 言 专 栏&#xff1a;C语言&#xff1a;从入…

分享一个超级实用的东西——巴比达远程访问

前言 &#x1f388;家人们&#xff0c;今天我要和你们分享一个超级实用的东西——巴比达远程访问&#xff01;&#x1f389; &#x1f4bb;有了它&#xff0c;无论你身在何处&#xff0c;都能轻松访问家中的电脑&#x1f4bb;&#xff0c;就像在身边一样方便&#xff01;&…

C++类型转换可调用对象

目录 C的四种可视性类型转换 1.static_cast 2.reinterpret_cast 3.const_cast 4.dynamic_cast C中的可调用对象 普通函数 函数指针 仿函数 Lambda表达式 包装器function bind C的四种可视性类型转换 C语言中的类型转换是不安全、不明确的&#xff0c;于是C就出了更…

JavaFX布局-BorderPane

JavaFX布局-BorderPane 实现方式Java实现FXML实现 综合案例 将容器空间分成五个区域&#xff1a;顶部&#xff08;Top&#xff09;、底部&#xff08;Bottom&#xff09;、左侧&#xff08;Left&#xff09;、右侧&#xff08;Right&#xff09;和中心&#xff08;Center&#…

专题六:Spring源码之初始化容器BeanFactory

上一篇咱们通过一个例子介绍初始化容器上下文相关内容&#xff0c;并通过两个示例代码看到了Spring在设计阶段为我预留的扩展点&#xff0c;和我们应该如何利用这两个扩展点在Spring初始化容器上下文阶段为我们提供服务。这一篇咱们接着往下看。 老这样子下回到refresh方法上来…

OFDM关键技术——同步技术

同一符号内各子载波受到不同的相位偏转及幅度衰减&#xff0c; k 越大偏差越大&#xff1b;相位偏转与子载波序号 k 和符号序号 i 均有关&#xff0c;序号越大&#xff0c;相位偏转越大&#xff1b;引入了 ICI &#xff0c;系统信噪比降低&#xff1b;当采样偏差效果累积到一定…

苍穹外卖项目 常用注解 + 动态sql

常用注解 常见的注解解析方法有两种&#xff1a; 编译期直接扫描&#xff1a;编译器在编译 Java 代码的时候扫描对应的注解并处理&#xff0c;比如某个方法使用Override 注解&#xff0c;编译器在编译的时候就会检测当前的方法是否重写了父类对应的方法。运行期通过反射处理&…

CesiumJS【Basic】- #038 绘制轮廓线(Primitive方式)

文章目录 绘制轮廓线(Primitive方式)1 目标2 代码2.1 main.ts绘制轮廓线(Primitive方式) 1 目标 使用Primitive方式绘制轮廓线 2 代码 2.1 main.ts var start = Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883);v

设备通信-MODBUS协议和485接口

因水表远程监控和水泵数据监控系统&#xff0c;需了解物联网开发协议。 通信协议 通信协议说白了就是一种语言&#xff0c;一种通信双方都能听的懂得语言。 设备常用的通信协议有MODBUS RTU&#xff0c;PPI,MPI等&#xff0c;通信协议和我们常用的语言只是叫法不一样&#x…

预约小程序源码,云开发技术,无需服务器

介绍&#xff1a; 很多企业的业务都需要通过服务预约来完成&#xff0c;比如酒店、美容、家政等等。 但很多商家因缺少合适的服务预订工具&#xff0c;而不知道如何让客户尽快预约。 这种情况下&#xff0c;制作一个自己的预约小程序&#xff0c;客户只需要扫码或者在微信里…

8605 删数问题

这是一个典型的贪心算法问题。我们可以从高位开始&#xff0c;找到第一个比后面数字大的数字&#xff0c;删除它&#xff0c;然后继续这个过程&#xff0c;直到删除k个数字。如果我们已经删除了k个数字&#xff0c;但是还没有找到一个比后面数字大的数字&#xff0c;那么我们就…

51-1 内网信息收集 - 内网资源探测

导语 在内网渗透过程中,通常需要利用各种技术来探测内网资源,为后续的横向渗透做准备。发现内网存活的主机及其详细信息可以帮助确定攻击方向和潜在的漏洞。 一、基于 ICMP 发现存活主机 ICMP(Internet Control Message Protocol,因特网控制消息协议)是 TCP/IP 协议簇的…

Vue2动态代理,换服务无须重启项目

1、痛点 当我们需要使用不同的服务器时&#xff0c;就需要手动修改vue.config.js中配置并重新启动项目。当项目越来越大时&#xff0c;会需要较长的时间来等待项目启动&#xff0c;如此反复&#xff0c;极大影响我们开发进度。 2、寻求解决方案 vue-cli 的代理是使用的http-p…