[算法] 优先算法(四):滑动窗口(下)

🌸个人主页:https://blog.csdn.net/2301_80050796?spm=1000.2115.3001.5343
🏵️热门专栏:
🧊 Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm=1001.2014.3001.5482
🍕 Collection与数据结构 (92平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm=1001.2014.3001.5482
🧀Java EE(94平均质量分) https://blog.csdn.net/2301_80050796/category_12643370.html?spm=1001.2014.3001.5482
🍭MySql数据库(93平均质量分)https://blog.csdn.net/2301_80050796/category_12629890.html?spm=1001.2014.3001.5482
🍬算法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12676091.html?spm=1001.2014.3001.5482
感谢点赞与关注~~~
在这里插入图片描述
✒️ 期末考试结束,暑假回归,文章将会保持更新.

目录

  • 6. 水果成篮(难度:🟡3度)
  • 7. 找到字符串中的所有字母异位词(难度:🟠4度)
  • 8. 串联所有单词的子串(难度:🔴5度)

6. 水果成篮(难度:🟡3度)

OJ链接

  • 题目描述

你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 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] 这五棵树。

  • 算法原理
    研究的对象是⼀段连续的区间,可以使用「滑动窗口」思想来解决问题。
    让滑动窗口满足:窗口内水果的种类只有两种
    右端水果进入窗口的时候,用哈希表统计这个水果的频次。这个水果进来后,判断哈希表的大小:
    ▪ 如果大小超过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(int[] fruits) {Map<Integer,Integer> hash = new HashMap<>();int ret = 0;for (int right = 0,left = 0;right < fruits.length;right++){hash.put(fruits[right],hash.getOrDefault(fruits[right],0)+1);while(hash.size() > 2){hash.put(fruits[left],hash.get(fruits[left])-1);if (hash.get(fruits[left]) == 0){hash.remove(fruits[left]);}left++;}ret = Math.max(ret,right-left+1);}return ret;}
}

7. 找到字符串中的所有字母异位词(难度:🟠4度)

OJ链接

  • 题目描述

给定两个字符串 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” 的异位词。

  • 算法原理(滑动窗口+哈希表)
    • 首先这道题的窗口大小是固定的,大小就是p的长度.要是窗口大小小于或等于p的长度,就要进窗口,大于就要出窗口.
    • 这道题需要用到两个哈希表,hash1用来统计p中的字母种类及其个数.hash2用来统计窗口范围内的字母种类和个数.
    • 这道题还需要用count这个变量来统计窗口范围中有效的字符个数.
      • 如果窗口中某个字母的个数<=hash1中某个字母的个数,那么这个字母就是有效字母,在进窗口时要给count++,在出窗口的时候,就要给count–.
      • 在每一次进出窗口,并处理count之后,如果count == p.length(),说明count中全部是有效字母,这个区间就是要找的区间.记录在list中.
  • 代码实现
class Solution {public List<Integer> findAnagrams(String s, String p) {List<Integer> list = new ArrayList<>();Map<Character,Integer> hash1 = new HashMap<>();Map<Character,Integer> hash2 = new HashMap<>();for (int i = 0 ; i < p.length() ; i++){hash1.put(p.charAt(i),hash1.getOrDefault(p.charAt(i),0)+1);}int count = 0;//用来统计有效字符个数for (int left = 0,right = 0;right < s.length();right++){char in = s.charAt(right);hash2.put(in,hash2.getOrDefault(in,0)+1);//进窗口if (hash2.get(in) <= hash1.getOrDefault(in,0)){//大于hash1中的重复字符不计入count++;//统计有效字符}if (right-left+1 > p.length()){//窗口大于p的长度,出窗口char out = s.charAt(left);if (hash2.get(out) <= hash1.getOrDefault(out,0)){//看出的是否是有效字符count--;}hash2.put(out,hash2.get(out)-1);//判断完成之后再出窗口left++;}if (count == p.length()){//说明窗口里面全部是有效字符list.add(left);}}return list;}
}

8. 串联所有单词的子串(难度:🔴5度)

OJ链接

  • 题目描述

给定一个字符串 s 和一个字符串数组 words。 words 中所有字符串 长度相同
s 中的 串联子串 是指一个包含 words 中所有字符串以任意顺序排列连接起来的子串
例如,如果 words = [“ab”,“cd”,“ef”], 那么 “abcdef”, “abefcd”,“cdabef”, “cdefab”,“efabcd”, 和 “efcdab” 都是串联子串。 “acdbef” 不是串联子串,因为他不是任何 words 排列的连接
返回所有串联子串在 s 中的开始索引。你可以以 任意顺序 返回答案。
示例 1:
输入:s = “barfoothefoobarman”, words = [“foo”,“bar”]
输出:[0,9]
解释:因为 words.length == 2 同时 words[i].length == 3,连接的子字符串的长度必须为 6。
子串 “barfoo” 开始位置是 0。它是 words 中以 [“bar”,“foo”] 顺序排列的连接。
子串 “foobar” 开始位置是 9。它是 words 中以 [“foo”,“bar”] 顺序排列的连接。
输出顺序无关紧要。返回 [9,0] 也是可以的。
示例 2:
输入:s = “wordgoodgoodgoodbestword”, words = [“word”,“good”,“best”,“word”]
输出:[]
解释:因为 words.length == 4 并且 words[i].length == 4,所以串联子串的长度必须为 16。
s 中没有子串长度为 16 并且等于 words 的任何顺序排列的连接。
所以我们返回一个空数组。
示例 3:
输入:s = “barfoofoobarthefoobarman”, words = [“bar”,“foo”,“the”]
输出:[6,9,12]
解释:因为 words.length == 3 并且 words[i].length == 3,所以串联子串的长度必须为 9。
子串 “foobarthe” 开始位置是 6。它是 words 中以 [“foo”,“bar”,“the”] 顺序排列的连接。
子串 “barthefoo” 开始位置是 9。它是 words 中以 [“bar”,“the”,“foo”] 顺序排列的连接。
子串 “thefoobar” 开始位置是 12。它是 words 中以 [“the”,“foo”,“bar”] 顺序排列的连接。

  • 算法原理(滑动窗口+哈希表)
    这道题的算法原理与上一道题非常类似,只不过现在的对象不是字母,而是字符串,只需要把一个个的字符串看成一个个的字母即可.
    但是这道题还是有和上一道题不一样的地方,一共有三点:
    • 哈希表存放元素的种类不一样,hash<String,int>.
    • left与right指针移动的步长不一样,这里移动的步长是words中每个单词的长度.
    • 滑动窗口执行的次数不一样,一共执行words中每个单词的长度的次数.原理如下图:
      在这里插入图片描述
  • 代码实现
class Solution {public List<Integer> findSubstring(String s, String[] words) {List<Integer> list = new ArrayList<>();Map<String,Integer> hash1 = new HashMap<>();int len = words[0].length();for (int i = 0;i < words.length;i++){hash1.put(words[i],hash1.getOrDefault(words[i],0)+1);}for (int i = 0;i < len;i++){//滑动窗口执行的次数int count = 0;Map<String,Integer> hash2 = new HashMap<>();for (int left = i,right = i;right+len <= s.length();right+=len){String in = s.substring(right,right+len);hash2.put(in,hash2.getOrDefault(in,0)+1);if (hash2.get(in) <= hash1.getOrDefault(in,0)){count++;}if (right-left+1 > words.length*len){String out = s.substring(left,left+len);if (hash2.get(out) <= hash1.getOrDefault(out,0)){count--;}hash2.put(out,hash2.getOrDefault(out,0)-1);left += len;}if (words.length == count){list.add(left);}}}return list;}
}

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

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

相关文章

20240708 每日AI必读资讯

&#x1f916;破解ChatGPT惊人耗电&#xff01;DeepMind新算法训练提效13倍&#xff0c;能耗暴降10倍 - 谷歌DeepMind研究团队提出了一种加快AI训练的新方法——多模态对比学习与联合示例选择&#xff08;JEST&#xff09;&#xff0c;大大减少了所需的计算资源和时间。 - JE…

Java线程的创建·启动和休眠

一.线程的创建和启动 Java中创建线程的两种方式 ◆继承java.lang.Thread类 ◆实现java.lang.Runnable接口 ◆使用线程的步骤 继承Thread类创建线程 ◆自定义线程类继承自Thread类 ◆重写run()方法&#xff0c;编写线程执行体 ◆创建线程对象&#xff0c;调用start()方法启动…

目标检测YOLO实战应用案例100讲-基于深度学习的无人机影像小目标识别(续)

目录 3.2 实验平台和环境 3.3 实验评价指标 3.4 基础框架YOLOv5在无人机数据集上的实验 3.4.1 实验结果 3.4.2 结果分析 4基于深度学习的无人机影像目标检测算法 4.1 基于改进YOLOv5的小目标检测算法研究 4.1.1 增加注意力机制 4.1.2 增加检测层 4.1.3多尺…

2024年 春秋杯 网络安全联赛夏季赛 Web方向 题解WirteUp 部分

brother 题目描述&#xff1a;web哥&#xff0c;打点容易提权难。 打点就是最简单的SSTI。 执行下find / -user root -perm -4000 -print 2>/dev/null找一下具备suid权限的命令 /usr/lib/dbus-1.0/dbus-daemon-launch-helper /usr/bin/chsh /usr/bin/gpasswd /usr/bin/n…

互联网十万个为什么之什么是数据备份?

数据备份是按照一定的备份频率创建数据副本的过程&#xff0c;将重要的数据复制到其它位置或者存储介质&#xff0c;并对生成的副本保留一定的时长。备份通常储存在不同的物理介质或云端&#xff0c;以确保数据的连续性和完整性。有效的备份策略至关重要&#xff0c;以防止数据…

macos 10.15系统下载包,macOS Catalina for mac

macOS Catalina 让你喜欢的种种 Mac 体验都更进一步。你可以领略音乐、播客这两款全新 Mac app 的表演&#xff1b;在 Mac 上畅享各款自己心爱的 iPad app&#xff1b;拿起 iPad 和 Apple Pencil&#xff0c;拓展工作空间&#xff0c;释放创意灵感&#xff1b;再打开那些平时常…

【STL】vector的模拟实现

目录 vector的介绍和使用 vector的介绍 vector的使用 构造函数 迭代器 空间增长问题 vector的增删查改等 vector的迭代器失效问题 vector的模拟实现 insert reserve push_back push_front resize erase pop_back pop_front 代码 vector的介绍和使用 vecto…

【PB案例学习笔记】-29制作一个调用帮助文档的小功能

写在前面 这是PB案例学习笔记系列文章的第29篇&#xff0c;该系列文章适合具有一定PB基础的读者。 通过一个个由浅入深的编程实战案例学习&#xff0c;提高编程技巧&#xff0c;以保证小伙伴们能应付公司的各种开发需求。 文章中设计到的源码&#xff0c;小凡都上传到了gite…

个人视角,社会影响力:自媒体的魅力所在

随着数字化时代的到来&#xff0c;自媒体正成为信息传播领域的一场革命。个人视角与社会影响力的结合&#xff0c;赋予了自媒体独特的魅力。在传统媒体受限制的同时&#xff0c;自媒体为每个人提供了表达自己观点和思想的自由。个体的真实视角使得自媒体在信息传播中发挥着重要…

14-40 剑和诗人14 - 为什么机器学习需要合成数据

​​​​​​ 数据是人工智能的命脉。如果没有高质量、有代表性的训练数据&#xff0c;我们的机器学习模型将毫无用处。但随着神经网络规模越来越大、人工智能项目越来越雄心勃勃&#xff0c;人们对数据的需求也越来越大&#xff0c;我们面临着一场危机——现实世界的数据收集和…

如何优化 PostgreSQL 中对于复杂数学计算的查询?

文章目录 一、理解复杂数学计算的特点二、优化原则&#xff08;一&#xff09;索引优化&#xff08;二&#xff09;查询重写&#xff08;三&#xff09;数据库配置调整&#xff08;四&#xff09;使用数据库内置函数的优势 三、具体的优化方案和示例&#xff08;一&#xff09;…

华为开源自研AI框架昇思MindSpore应用案例:FCN图像语义分割

Mask R-CNN MaskRCNN是一种概念简单、灵活、通用的目标实例分割框架&#xff0c;在检测出图像中目标的同时&#xff0c;还为每一个实例生成高质量掩码。这种称为Mask R-CNN的方法&#xff0c;通过添加与现有边框检测分支平行的预测目标掩码分支&#xff0c;达到扩展Faster R-CN…

leetcode判断二分图

判断二分图 图的问题肯定要用到深度优先遍历或者广度优先遍历&#xff0c;但又不是单纯的深度优先遍历算法和广度优先遍历算法&#xff0c;而是需要在遍历的过程中加入与解决题目相关的逻辑。 题干中说了&#xff0c;这个图可能不是连通图&#xff0c;这个提示有什么作用呢&a…

shared_ptr 线程安全

为什么 shared_ptr 可以安全地在多个线程中共享&#xff1f; 循环引用 因为shared_ptr std::shared_ptr 的引用计数是线程安全的。这意味着你可以在多个线程中安全地拷贝、赋值和销毁 std::shared_ptr。然而&#xff0c;访问或修改 shared_ptr 所指向的对象时&#xff0c;需要…

昇思25天学习打卡营第20天|LSTM+CRF序列标注

学AI还能赢奖品&#xff1f;每天30分钟&#xff0c;25天打通AI任督二脉 (qq.com) LSTMCRF序列标注 概述 序列标注指给定输入序列&#xff0c;给序列中每个Token进行标注标签的过程。序列标注问题通常用于从文本中进行信息抽取&#xff0c;包括分词(Word Segmentation)、词性标…

明日周刊-第15期

赶在周末结束前输出一把&#xff0c;周日的晚上大家要睡个好觉哦。 文章目录 一周热点资源分享言论歌曲推荐 一周热点 科技创新与基础设施建设 深中通道正式通车试运营 时间&#xff1a;6月30日 内容&#xff1a;国家重大工程深中通道正式通车试运营&#xff0c;标志着珠江口东…

吉时利KEITHLEY KI-488驱动和说明

吉时利KEITHLEY KI-488驱动和说明

[吃瓜教程]南瓜书第6章支持向量机

0.补充知识 0.1 超平面 定义&#xff1a; 超平面是指在&#x1d45b;维空间中&#xff0c;维度为 &#x1d45b;−1的子空间。它是分割空间的一个平面。 性质&#xff1a; n维空间的超平面 ( w T x b 0 , 其中 w , x ∈ R n ) (w^Tx_b0,其中w,x\in \mathbb R^n) (wTxb​0,其…

通过端口转发实现docker容器运行时端口更改

通过端口转发实现docker容器运行时端口更改 前言启动容器查看容器ip地址端口转发 前言 关于修改docker正在运行中容器端口&#xff0c;网上大部分分为3类: 1. 删除原有容器重新创建;2. 改配置文件;3. 在现有容器上新提交镜像&#xff0c;用新镜像起新的容器。 1和3属于同一种流…

探讨4层代理和7层代理行为以及如何获取真实客户端IP

准备工作 实验环境 IP角色192.168.1.100客户端请求IP192.168.1.100python 启动的HTTP服务192.168.1.102nginx服务192.168.1.103haproxy 服务 HTTP服务 这是一个简单的HTTP服务&#xff0c;主要打印HTTP报文用于分析客户端IP #!/usr/bin/env python # coding: utf-8import …