LeedCode刷题---滑动窗口问题(二)

顾得泉:个人主页

个人专栏:《Linux操作系统》  《C/C++》  《LeedCode刷题》

键盘敲烂,年薪百万!


一、将X减到0的最小操作数

题目链接:将 x 减到 0 的最小操作数

题目描述

       给你一个整数数组 nums 和一个整数 x 。每一次操作时,你应当移除数组 nums 最左边或最右边的元素,然后从 x 中减去该元素的值。请注意,需要 修改 数组以供接下来的操作使用。

       如果可以将 x 恰好 减到 0 ,返回 最小操作数 ;否则,返回 -1 。

示例 1:

输入:nums = [1,1,4,2,3], x = 5
输出:2
解释:最佳解决方案是移除后两个元素,将 x 减到 0 。

示例 2:

输入:nums = [5,6,7,8,9], x = 4
输出:-1

示例 3:

输入:nums = [3,2,20,1,1,3], x = 10
输出:5
解释:最佳解决方案是移除后三个元素和前两个元素(总共 5 次操作),将 x 减到 0 

提示:

  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 104
  • 1 <= x <= 109

解法

算法思路:

       题目要求的是数组「左端+右端」两段连续的、和为×的最短数组,信息量稍微多一些,不易理清思路;我们可以转化成求数组内一段连续的、和为sum(nums) - x的最长数组。此时,就是熟悉的滑动窗口问题了。

算法流程:

     a.转化问题:求target = sum(nums) - ×。如果target < 0,问题无解;

     b.初始化左右指针l = 0,r = 0(滑动窗口区间表示为[l,r),左右区间是否开闭很重要,必须设定与代码一致),记录当前滑动窗口内数组和的变量sum = 0,记录当前满足条件数组的最大区间长度maxLen = -1;

     c. 当r小于等于数组长度时,一直循环:

         i.如果sum < target,右移右指针,直至变量和大于等于target,或右指针已经移到头;

         ii.如果sum > target,右移左指针,直至变量和小于等于target,或左指针已经移到头;

         ii.如果经过前两步的左右移动使得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;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;}
};

二、水果成篮

题目链接:水果成篮

题目描述

       你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果 种类 。

       你想要尽可能多地收集水果。然而,农场的主人设定了一些严格的规矩,你必须按照要求采摘水果:

  • 你只有 两个 篮子,并且每个篮子只能装 单一类型 的水果。每个篮子能够装的水果总量没有限制。
  • 你可以选择任意一棵树开始采摘,你必须从 每棵 树(包括开始采摘的树)上 恰好摘一个水果 。采摘的水果应当符合篮子中的水果类型。每采摘一次,你将会向右移动到下一棵树,并继续采摘。
  • 一旦你走到某棵树前,但水果不符合篮子的水果类型,那么就必须停止采摘。

给你一个整数数组 fruits ,返回你可以收集的水果的 最大 数目。

示例 1:

输入:fruits = [1,2,1]
输出:3
解释:可以采摘全部 3 棵树。

示例 2:

输入:fruits = [0,1,2,2]
输出:3
解释:可以采摘 [1,2,2] 这三棵树。
如果从第一棵树开始采摘,则只能采摘 [0,1] 这两棵树。

示例 3:

输入:fruits = [1,2,3,2,2]
输出:4
解释:可以采摘 [2,3,2,2] 这四棵树。
如果从第一棵树开始采摘,则只能采摘 [1,2] 这两棵树。

示例 4:

输入:fruits = [3,3,3,1,2,1,1,2,3,3,4]
输出:5
解释:可以采摘 [1,2,1,1,2] 这五棵树。

提示:

  • 1 <= fruits.length <= 105
  • 0 <= fruits[i] < fruits.length

解法

算法思路:

       研究的对象是一段连续的区间,可以使用「滑动窗口」思想来解决问题。让滑动窗口满足:窗口内水果的种类只有两种。

做法∶

       右端水果进入窗口的时候,用哈希表统计这个水果的频次。这个水果进来后,判断哈希表的大小;如果大小超过2:说明窗口内水果种类超过了两种。那么就从左侧开始依次将水果划出窗口,直到哈希表的大小小于等于2,然后更新结果;如果没有超过2,说明当前窗口内水果的种类不超过两种,直接更新结果ret。

算法流程:

     a.初始化哈希表hash来统计窗口内水果的种类和数量;

     b.初始化变量:左右指针left =0, right =0,记录结果的变量ret= 0;c. 当right小于数组大小的时候,一直执行下列循环:

         i.将当前水果放入哈希表中;

         ii.判断当前水果进来后,哈希表的大小:

       如果超过2;将左侧元素滑出窗口,并且在哈希表中将该元素的频次减一;

       如果这个元素的频次减一之后变成了0,就把该元素从哈希表中删除;。重复上述两个过程,直到哈希表中的大小不超过2;

         iii.更新结果ret;

         iv. right++,让下一个元素进入窗口;d.循环结束后,ret存的就是最终结果。

代码实现

class Solution 
{
public:int totalFruit(vector<int>& f) {unordered_map<int, int> hash; int ret = 0;for(int left = 0, right = 0; right < f.size(); right++){hash[f[right]]++; // 进窗⼝while(hash.size() > 2){hash[f[left]]--;if(hash[f[left]] == 0)hash.erase(f[left]);left++;}ret = max(ret, right - left + 1);}return ret;}

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

题目链接:找到字符串中所有字母异位词

题目描述

       给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。

       异位词 指由相同字母重排列形成的字符串(包括相同的字符串)

示例 1:

输入: s = "cbaebabacd", p = "abc"
输出: [0,6]
解释:
起始索引等于 0 的子串是 "cba", 它是 "abc" 的异位词。
起始索引等于 6 的子串是 "bac", 它是 "abc" 的异位词。

 示例 2:

输入: s = "abab", p = "ab"
输出: [0,1,2]
解释:
起始索引等于 0 的子串是 "ab", 它是 "ab" 的异位词。
起始索引等于 1 的子串是 "ba", 它是 "ab" 的异位词。
起始索引等于 2 的子串是 "ab", 它是 "ab" 的异位词。

提示:

  • 1 <= s.length, p.length <= 3 * 104
  • s 和 p 仅包含小写字母

解法

算法思路:

       因为字符串p的异位词的长度一定与字符串p的长度相同,所以我们可以在字符串s中构造一个长度为与字符串p的长度相同的滑动窗口,并在滑动中维护窗口中每种字母的数量;当窗口中每种字母的数量与字符串p中每种字母的数量相同时,则说明当前窗口为字符串p的异位词;

       因此可以用两个大小为26的数组来模拟哈希表,一个来保存s 中的子串每个字符出现的个数,另一个来保存p中每一个字符出现的个数。这样就能判断两个串是否是异位词。

代码实现

class Solution 
{
public:vector<int> findAnagrams(string s, string p) {vector<int> ret;int hash1[26] = { 0 }; for(auto ch : p) hash1[ch - 'a']++;int hash2[26] = { 0 };int m = p.size();for(int left = 0, right = 0, count = 0; right < s.size(); right++){char in = s[right];if(++hash2[in - 'a'] <= hash1[in - 'a']) count++; if(right - left + 1 > m){char out = s[left++];if(hash2[out - 'a']-- <= hash1[out - 'a']) count--; }if(count == m) ret.push_back(left);}return ret;}
};

结语:今日的刷题分享到这里就结束了,希望本篇文章的分享会对大家的学习带来些许帮助,如果大家有什么问题,欢迎大家在评论区留言~~~ 

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

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

相关文章

mysql的负向条件查询会不会使用索引

mysql的负向条件查询&#xff0c;例如not in&#xff0c;会不会使用索引&#xff1f; 其实&#xff0c;mysql还是会尽量利用索引。如果查询的列上有索引&#xff0c;并且索引能够覆盖查询所需的列&#xff0c;那么mysql可能会使用索引来获取结果&#xff0c;而不是进行全表扫描…

2024中国国际大数据产业博览会年度主题征集公告

2024中国国际大数据产业博览会年度主题征集公告 中国国际大数据产业博览会&#xff08;以下简称数博会&#xff09;&#xff0c;是全球首个以大数据为主题的国家级博览会&#xff0c;由国家发展和改革委员会、工业和信息化部、国家互联网信息办公室和贵州省人民政府共同主办&am…

ADB命令安装卸载手机APP

前言 手机内置的浏览器很多广告&#xff0c;推荐的新闻也很多负面的新闻&#xff0c;所以就想卸载内置的手机app&#xff0c;不过现在很多手机都是限制了内置的软件都不能卸载&#xff0c;以前随便获取一下root权限&#xff0c;也是可以卸载的&#xff0c;不过最近搞了一下&am…

【POI的如何做大文件的写入】

&#x1f513;POI如何做大文件的写入 &#x1f3c6;文件和POI之间的区别是什么&#xff1f;&#x1f3c6;POI对于当今的社会发展有何重要性&#xff1f;&#x1f3c6;POI大文件的写入&#x1f396;️使用XSSF写入文件&#x1f396;️使用SXSSFWorkbook写入文件&#x1f396;️对…

设计可编辑表格组件

前言 什么是可编辑表格呢&#xff1f;简单来说就是在一个表格里面进行表单操作&#xff0c;执行增删改查。这在一些后台管理系统中是尤为常见的。 今天我们根据vue2 element-ui来设计一个表单表格组件。&#xff08;不涉及完整代码&#xff0c;想要使用完整功能可以看底部连…

ReenterLock重入锁

synchronized就是一种最简单的控制方法&#xff0c;它决定了一个线程释放可以访问临界区资源。 同时&#xff0c;Object.wait()方法和Object.notify()方法起到了线程等待和通知的作用。 ReenterLock重入锁可以完全替代关键字Synchoronized.重入锁是Synchoronized、Object.wait(…

[楚慧杯 2023] web

文章目录 eaaevalupload_shell eaaeval 打开题目&#xff0c;源码给了用户密码 登陆后啥也没有&#xff0c;扫一下发现源码泄露www.zip <?php class Flag{public $a;public $b;public function __construct(){$this->a admin;$this->b admin;}public function _…

C++ list常用操作

目录 一、介绍 二、list的常用操作 1、构造 2、迭代器 3、元素访问 4、容量操作 一、介绍 std::list文档链接 list是可以在常数范围内在任意位置进行插入和删除的序列式容器&#xff0c;并且该容器可以前后双向迭代。list的底层是双向链表结构&#xff0c;双向链表中每个…

独立看门狗 IWDG

看门狗介绍 "看门狗"通常指的是计算机科学和信息技术领域中的一种技术或设备&#xff0c;用于监控系统的运行状态&#xff0c;并在系统出现故障或异常情况时采取相应的措施。这种技术或设备起到类似于守卫的作用&#xff0c;确保系统的稳定性和可靠性。 在计算机系统…

beebox靶场A1 low 命令注入通关教程(上)

一&#xff1a;html注入 get HTML注入&#xff0c;就是当用户进行输入时&#xff0c;服务器没有对用户输入的数据进行过滤或转义&#xff0c;导致所有输入均被返回前端&#xff0c;网页解析器会将这些数据当作html代码进行解析,这就导致一些恶意代码会被正常执行。 首先进行简…

DC电源模块的设计与制造技术创新

BOSHIDA DC电源模块的设计与制造技术创新 DC电源模块的设计与制造技术创新主要涉及以下几个方面&#xff1a; 1. 高效率设计&#xff1a;传统的DC电源模块存在能量转换损耗较大的问题&#xff0c;技术创新可通过采用高效率的电路拓扑结构、使用高性能的功率开关器件和优化控制…

面向对象三大特征——继承

目录 1. 概述 2. 继承的限制 2.1 单继承 2.2 访问修饰符 2.3 . final 3. 重写 4. super 4.1super的作用 4.2访问父类的成员和被重写方法 4.3调用父类的构造器 1. 概述 多个类中存在相同属性和行为时&#xff0c;将这些内容抽取到单独一个类中&#xff0c;那么就无需在…

C++类与对象 (上)

目录 前言&#xff1a; 类和对象的理解 类的引入 类的定义与使用方式 访问限定符 类的两种定义方式 成员变量的命名规则 类的作用域 类的实例化 类对象模型 计算类对象的大小 类对象的存储方式 this指针 前言&#xff1a; C语言是面向过程的&#xff0c;关注的是过…

基于Java SSM框架实现智能停车场系统项目【项目源码+论文说明】

基于java的SSM框架实现智能停车场系统演示 摘要 本论文主要论述了如何使用JAVA语言开发一个智能停车场管理系统&#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;采用B/S架构&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff0c;作者将论述…

图扑物联助力打造现代化绿色智慧港口

“智慧港口”是以现代化基础设施设备为基础&#xff0c;以云计算、大数据、物联网、移动互联网、智能控制等新一代信息技术与港口运输业务深度融合为核心&#xff0c;以港口运输组织服务创新为动力&#xff0c;以完善的机制、法律法规、标准规范、发展政策为保障。能够在更高层…

Element 介绍

Element 介绍 Vue 快速入门 Vue 常见组件 表格 分页组件 其他自己去看吧 链接: 其他组件

设计模式——装饰模式(结构型)

引言 装饰模式是一种结构型设计模式&#xff0c; 允许你通过将对象放入包含行为的特殊封装对象中来为原对象绑定新的行为。 假设你正在开发一个提供通知功能的库&#xff0c; 其他程序可使用它向用户发送关于重要事件的通知。 库的最初版本基于 通知器Notifier类&#xff0c;…

Oracle RAC环境下redo log 文件的扩容

环境&#xff1a; 有一个2节点RAC每一个节点2个logfile group每一个group含2个member每一个member的大小为200M 目标&#xff1a;将每一个member的大小有200M扩充到1G。 先来看下redo log的配置&#xff1a; SQL> select * from v$log;GROUP# THREAD# SEQUENCE# …

JUC并发编程 06——Synchronized与锁升级

一.Java对象内存布局和对象头 在HotSpot虚拟机里&#xff0c;对象在堆内存中的存储布局可以划分为三个部分&#xff1a;对象头(Header) 、实例数据 (Instance Data) 和 对文填充 (Padding)。 对象内部结构分为&#xff1a;对象头、实例数据、对齐填充&#xff08;保证8个字节的…

软件设计师——计算机组成原理(三)

&#x1f4d1;前言 本文主要是【计算机组成原理】——软件设计师——计算机组成原理的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是听风与他&#x1f947; ☁️博客首页&#xff1a;CSDN主页听风与他 …