[Algorithm][滑动窗口][水果成篮][最大连续的一个数 Ⅲ][将x减到0的最小操作数]详细讲解

目录

  • 1.水果成篮
    • 1.题目链接
    • 2.算法原理讲解
    • 3.代码讲解
  • 2.找到字符串中所有字母异位词
    • 1.题目链接
    • 2.算法原理讲解
    • 3.代码实现
  • 3.串联所有单词的字串
    • 1.题目链接
    • 2.算法原理讲解
    • 3.代码实现
  • 3.最小覆盖字串
    • 1.题目链接
    • 2.算法原理讲解


1.水果成篮

1.题目链接

  • 水果成篮

2.算法原理讲解

  • 研究的对象是⼀段连续的区间,可以使⽤**「滑动窗⼝」**思想来解决问题
    • 将问题转化为:找出一个最长的子数组长度,子数组中不超过两种类型的水果
  • 让滑动窗⼝满⾜:窗⼝内⽔果的种类只有两种
  • 做法
    • 右端⽔果进⼊窗⼝的时候,⽤哈希表统计这个⽔果的频次
    • 这个⽔果进来后,判断哈希表的⼤⼩
      • 如果⼤⼩超过2:说明窗⼝内⽔果种类超过了两种
        • 那么就从左侧开始依次将⽔果划出窗⼝,直到哈希表的⼤⼩⼩于等于2,然后更新结果
      • 如果没有超过2:说明当前窗⼝内⽔果的种类不超过两种,直接更新结果ret
  • 优化
    • v1.0中,哈希表有大量的插入删除
    • v2.0中,由于水果类型最大值是一个定值,所以可以把hash数组写死,这样以空间换时间,不会存在哈希冲突
      • 此时不用STL容器,无法 O ( 1 ) O(1) O(1)判断水果种类数量,此时添加一个变量kinds即可
        请添加图片描述

3.代码讲解

// v1.0
// 模型转化为:数组只有两个元素的最大子数组
int TotalFruit(vector<int>& fruits) 
{int ret = 0;unordered_map<int, int> basket; // <水果种类 数量>for(int left = 0, right = 0; right < fruits.size(); right++){basket[fruits[right]]++; // 入窗口while(basket.size() > 2) // 判断{// 出窗口basket[fruits[left]]--;if(basket[fruits[left]] == 0){basket.erase(fruits[left]);}left++;}ret = max(ret, right - left + 1); // 更新数据}return ret;
}
---------------------------------------------------------------
// v2.0 优化
// 改造哈希表,以改善时间复杂度
int TotalFruit(vector<int>& fruits) 
{int ret = 0, kinds = 0;// 水果类型小于一个定值// 以空间换时间int basket[100001] = { 0 };for(int left = 0, right = 0; right < fruits.size(); right++){if(basket[fruits[right]] == 0){kinds++;}basket[fruits[right]]++; // 入窗口while(kinds > 2) // 判断{// 出窗口basket[fruits[left]]--;if(basket[fruits[left]] == 0){kinds--;}left++;}ret = max(ret, right - left + 1); // 更新数据}return ret;
}

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

1.题目链接

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

2.算法原理讲解

  • 思路:「滑动窗⼝」 + 「哈希表」
  • 做法
    • 因为字符串p的异位词的⻓度⼀定与字符串p的⻓度相同
      • 所以可以在字符串s中构造⼀个⻓度为与字符串p的⻓度相同的滑动窗⼝,并在滑动中维护窗⼝中每种字⺟的数量
    • 当窗⼝中每种字⺟的数量与字符串p中每种字⺟的数量相同时,则说明当前窗⼝为字符串 p的异位词
    • 因此可以⽤两个⼤⼩为26的数组来模拟哈希表
      • ⼀个来保存s中的⼦串每个字符出现的个数
      • 另⼀个来保存p中每⼀个字符出现的个数
      • 这样就能判断两个串是否是异位词
        ![[Pasted image 20240326190744.png]]
  • 优化:更新结果的判断条件 -> 利用count来统计窗口中"有效字符"的个数
    • 进窗口:进入后 -> if (hashS[in] <= hashP[in]) -> count++
    • 出窗口:出去前 -> if (hashS[out] <= hashP[out]) -> count--
    • 更新结果:count == len

3.代码实现

// 将问题转化为:p中的字母出现的次数与s中某个字串中出现的次数相同
// v1.0
vector<int> FindAnagrams(string s, string p) 
{vector<int> ret;int hashS[26] = { 0 };int hashP[26] = { 0 };// 将p如hashfor(auto& ch : p){hashP[ch - 'a']++;}// 处理sint len = p.size();for(int left = 0, right = 0; right < s.size(); right++){hashS[s[right] - 'a']++; // 入窗口if(right - left + 1 > len) // 判断窗口是否大了{hashS[s[left++] - 'a']--; // 出窗口}if(right - left + 1 == len) // 尝试更新数据{bool flag = true;for(int i = 0; i < 26; i++){if(hashP[i] != hashS[i]){flag = false;break;}}if(flag){ret.push_back(left);}}}return ret;
}
-----------------------------------------------------------------
// v2.0 优化更新结果的判断条件,不用每次都遍历hash了
vector<int> findAnagrams(string s, string p) 
{vector<int> ret;int hashS[26] = { 0 };int hashP[26] = { 0 };// 将p如hashfor(auto& ch : p){hashP[ch - 'a']++;}// 处理sint count = 0, len = p.size();for(int left = 0, right = 0; right < s.size(); right++){// 入窗口 + 维护countif(++hashS[s[right] - 'a'] <= hashP[s[right] - 'a']){count++; // 入窗口的字符是一个有效字符}if(right - left + 1 > len) // 判断窗口是否大了{// 维护countif(hashS[s[left] - 'a']-- <= hashP[s[left] - 'a']){count--; // 出窗口的元素是一个有效字符}left++; // 出窗口}if(count == len) // 更新结果{ret.push_back(left);}}return ret;
}

3.串联所有单词的字串

1.题目链接

  • 串联所有单词的字串

2.算法原理讲解

  • 如果把每⼀个单词看成⼀个字⺟,问题就变成了找到**「字符串中所有的字⺟异位词」**
    • ⽆⾮就是之前处理的对象是⼀个⼀个的字符,这⾥处理的对象是⼀个⼀个的单词
  • 注意的点 && 区别
    • 哈希表:hash<string, int>
    • left指针与right指针的移动
      • 移动的步长,是单词的长度len -> 一次跨过一个单词
    • 滑动窗口执行的次数:len
      • 因为无法确定起点是在哪儿,所以要执行len
      • 大于len次则没必要,因为第一次与第len+1次是重复的情况…
        请添加图片描述

3.代码实现

vector<int> findSubstring(string s, vector<string>& words) 
{int len = words[0].size();unordered_map<string, int> mapS;unordered_map<string, int> mapV;vector<int> ret;for(auto& str : words){mapV[str]++;}for(int i = 0; i < len; i++) // 滑动窗口的执行次数{int count = 0;for(int left = i, right = i; right + len <= s.size(); right += len){// 入窗口,截取子串,维护countstring str = s.substr(right, len);mapS[str]++;// 看看mapV中是否存在str,以避免插入不需要的值if(mapV.count(str) && mapS[str] <= mapV[str]) {count++;}// 判断窗口是否大了if(((right - left + len) / len) > words.size()){// 维护countstring tmp = s.substr(left, len);if(mapV.count(tmp) && mapS[tmp]-- <= mapV[tmp]){count--;}left += len; // 出窗口}if(count == words.size()) // 更新结果{ret.push_back(left);}}mapS.clear();}return ret;
}

3.最小覆盖字串

1.题目链接

  • 最小覆盖字串

2.算法原理讲解

  • 研究对象是连续区间,因此可以尝试使⽤「滑动窗⼝」的思想来解决

  • 如何判断当前窗⼝内的所有字符是符合要求的呢?

    • 可以使⽤两个哈希表,其中⼀个将⽬标串的信息统计起来,另⼀个哈希表动态的维护窗⼝ 内字符串的信息

    • 当动态哈希表中包含⽬标串中所有的字符,并且对应的个数都不⼩于⽬标串的哈希表中各个字符的个数,那么当前的窗⼝就是⼀种可⾏的⽅案

      请添加图片描述

  • 优化:判断条件 -> 使用变量count标记有效字符的种类
    请添加图片描述

string MinWindow(string s, string t) 
{// 仅用数组可以避免STL的开销,提高效率int hashS[128] = { 0 };int hashT[128] = { 0 };int kinds = 0;for(auto& ch : t){if(hashT[ch]++ == 0){kinds++;}}int begin = -1, minLen = INT_MAX;for(int left = 0, right = 0, count = 0; right < s.size(); right++){// 入窗口char in = s[right];// 维护count,仅统计t中有效字符的种类if(++hashS[in] == hashT[in]){count++;}while(count == kinds) // 判断{   // 更新if(right - left + 1 < minLen){begin = left;    minLen = right - left + 1;}// 出窗口 && 维护countchar out = s[left++];if(hashS[out]-- == hashT[out]){count--;}}}string ret = "";if(begin != -1){ret = s.substr(begin, minLen);    }return ret;
}

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

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

相关文章

机器学习|决策树|如何计算信息增益|方法总结

如是我闻 &#xff1a;那你说决策树这块还能考点啥呢&#xff0c;也就是算算属性的信息增益&#xff08;Information Gain&#xff09;了&#xff0c; 信息增益是一种评估特征&#xff08;属性&#xff09;在分类任务中重要性的方法&#xff0c;它基于熵的概念来计算。熵是一个…

notepad++快捷键和宏录制

想要一个删除行的快捷键, 发现没有 有个现成的快捷键 CtrlL : 剪切当前行 , 不是我想要的效果 宏录制很方便,于是就录制一个删除行的宏,设置快捷键为: CtrlD 录制宏: 1, 点击"开始录制" 2, 依次按键: End , Space , Shift Home , Delete , Delete 3, 点击"停止…

Java集合进阶——数据结构

1.栈 模型&#xff1a; 栈模型和一个杯子差不多&#xff0c;一端开口&#xff0c;一端封闭&#xff0c;开口的那端叫栈顶&#xff0c;封闭的那端叫栈底&#xff0c;如图所示 介绍&#xff1a; 元素进入栈中叫进栈/压栈&#xff0c;元素出来叫出栈&#xff0c;元素进栈后会先来…

Appian发布最新版本:通过AI流程自动化推动业务发展

Appian公司于2024年4月16日在弗吉尼亚州麦克莱恩宣布推出Appian平台的最新版本。此版本引入了Process HQ&#xff0c;这是一个集流程挖掘和企业AI于一体的系统&#xff0c;结合了Appian的数据平台。Process HQ为企业运营提供前所未有的可见性&#xff0c;支持数据驱动的决策和流…

CERLAB无人机自主框架: 2-动态目标检测与跟踪

前言&#xff1a;更多更新文章详见我的个人博客主页【MGodmonkeyの世界】 描述&#xff1a;欢迎来到CERLAB无人机自主框架&#xff0c;这是一个用于自主无人飞行器 (UAV) 的多功能模块化框架。该框架包括不同的组件 (模拟器&#xff0c;感知&#xff0c;映射&#xff0c;规划和…

Hadoop——Yarn 调度器和调度算法

Yarn 调度器和调度算法 YARN调度器&#xff08;Scheduler&#xff09;是负责将集群资源分配给不同应用程序的组件。它根据应用程序的资源需求和优先级&#xff0c;以及集群的资源供给情况&#xff0c;决定如何分配资源。YARN提供了多种调度器实现&#xff0c;每种调度器都有不…

如何通过MSTSC连接Ubuntu的远程桌面?

正文共&#xff1a;666 字 12 图&#xff0c;预估阅读时间&#xff1a;1 分钟 前面我们介绍了如何通过VNC连接Ubuntu 18.04的远程桌面&#xff08;Ubuntu 18.04开启远程桌面连接&#xff09;&#xff0c;非常简单。但是有小伙伴咨询如何使用微软的远程桌面连接MSTSC&#xff08…

Go栈内存管理源码解读

基本介绍 栈内存一般是由Go编译器自动分配和释放&#xff0c;其中存储着函数的入参和局部变量&#xff0c;这些参数和变量随着函数调用而创建&#xff0c;当调用结束后也会随之被回收。通常开发者不需要关注内存是分配在堆上还是栈上&#xff0c;这部分由编译器在编译阶段通过…

Android Studio学习笔记——广播机制Broadcast

Android Studio学习笔记——广播机制 5.1 广播机制简介5.2 接收系统广播5.2.1 动态注册监听网络变化5.2.2 静态注册实现开机启动 5.3 发送自定义广播5.3.1 发送标准广播5.3.2 发送有序广播 5.4 使用本地广播5.5 广播的最佳实践——强制下线功能 5.1 广播机制简介 安卓每个应用…

web server apache tomcat11-08-JNDI Resources

前言 整理这个官方翻译的系列&#xff0c;原因是网上大部分的 tomcat 版本比较旧&#xff0c;此版本为 v11 最新的版本。 开源项目 从零手写实现 tomcat minicat 别称【嗅虎】心有猛虎&#xff0c;轻嗅蔷薇。 系列文章 web server apache tomcat11-01-官方文档入门介绍 web…

spring boot后端开发基础

spring boot后端开发基础 Spring Boot一、开发步骤二、Web分析三、跨域问题四、HTTP协议五、Web服务器六、响应前端请求七、springboot常用注解创建一个简单的RESTful API服务层和数据访问层配置类和Bean定义响应体和路径变量 Spring Boot 一、开发步骤 创建项目 添加依赖 项…

k8s部署Eureka集群

部署有状态负载 镜像配置&#xff1a; 环境变量如下&#xff1a; AUTHENTICATE_ENABLEtrue JAVA_OPTS-Dauth.userName账号 -Dauth.password密码 MY_POD_NAMEmetadata.name BOOL_REGISTERtrue BOOL_FETCHtrue APPLICATION_NAME负载名称 EUREKA_INSTANCE_HOSTNAME${MY_POD_NA…

webpack源码分析——enhanced-resolve库之getType、normalize、join和cachedJoin函数

一、PathType 路径类型 const PathType Object.freeze({Empty: 0, // 空Normal: 1, // 默认值Relative: 2, // 相对路径AbsoluteWin: 3, // win 下的绝对路径AbsolutePosix: 4, // posix 下的绝对路径Internal: 5 // enhanced-resolve 内部自定义的一种类型&#xff0c;具体是…

小程序AI智能名片S2B2C商城系统:做内容、造IP、玩社群打造私域流量的新营销秘籍

在数字化浪潮汹涌的新时代&#xff0c;小程序AI智能名片S2B2C商城系统正以其独特的魅力&#xff0c;引领着营销领域的新变革。这套系统不仅将人工智能与小程序技术完美结合&#xff0c;更通过创新的S2B2C模式&#xff0c;为企业打开了一扇通往成功的大门。 面对激烈的市场竞争&…

SQL注入作业

目录 一、万能密码和二阶注入测试 1.万能密码 2.二阶注入测试 二、联合查询注入测试 1.判断注入点 2.判断当前查询语句的列数 3.查询数据库基本信息 4.查询数据库中的数据 三、报错注入 1. 报错注入函数EXTRATVALUE 2.UPDATEXML 四、盲注测试 1.布尔盲注 判断数据…

Linux搭建Discuz论坛

搭建一个论坛 —接上篇博客 改名/etc/httpd/conf.d/vhosts.conf 》/etc/httpd/conf.d/vhosts.conf.bak [rootlocalhost conf.d]# mv /etc/httpd/conf.d/vhosts.conf /etc/httpd/conf.d/vhosts.conf.bak此时的vhosts.conf是一个新创建的文件&#xff0c;之前的vhosts.conf已经…

使用 Godot 游戏引擎为 Apple 的 visionOS 创建游戏和应用的平台

借助GodotVision ,您可以使用Godot 游戏引擎为 Apple VisionOS创建游戏和应用程序。 保卫牛城堡,一款使用 GodotVision 制作的 VisionOS 游戏 GodotVision 运行一个控制本机RealityKit 视图的无头 Godot实例。粗略地说:Godot 是后端,

毅速3D打印随形透气钢:革新传统,引领未来

透气钢&#xff0c;这种多孔金属材料&#xff0c;既融合了金属材料的坚固性&#xff0c;又具备了透气材料的通透性。尤其在注塑模具的制造中&#xff0c;透气钢的作用不可忽视。通过镶嵌透气钢&#xff0c;能够有效解决因困气产生的注塑问题&#xff0c;使成型加工更为完善&…

【机器学习】机器学习学习笔记 - 监督学习 - 逻辑回归分类朴素贝叶斯分类支持向量机 SVM (可分类、可回归) - 04

逻辑回归分类 import numpy as np from sklearn import linear_modelX np.array([[4, 7], [3.5, 8], [3.1, 6.2], [0.5, 1], [1, 2], [1.2, 1.9], [6, 2], [5.7, 1.5], [5.4, 2.2]]) y np.array([0, 0, 0, 1, 1, 1, 2, 2, 2])# 逻辑回归分类器 # solver&#xff1a;求解器&a…

C字符串操作strlenstrnlen_s详解

前言 strcat、strcpy、strcmp、strlen是C中针对字符串的库函数&#xff0c;这四个函数不安全&#xff0c;然后C针对这个情况整出strcat_s、strcpy_s、strncmp、strnlen_s(这个并不是替代stelen的)来弥补。 这篇文章主要讲&#xff1a;strlen以及strnlen_s的用法。 详见C字符串…