3. 无重复字符的最长子串/438. 找到字符串中所有字母异位词/560. 和为 K 的子数组

news/2024/5/18 17:12:35

3. 无重复字符的最长子串

给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。

示例 1:

输入: s = "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

思路:想象一下我们自己是怎么判断无重复的,先以第K个字符开始,依次加入字符,直到遇到重复的,这里抽象成代码语言就是:需要两个指针(左右指针去移动),还需要一个能存储字符的数据结构,并且可以判断重复。所以我们就可以采用滑动窗口去处理,对于判断重复用的数据结构为哈希集合(即 C++ 中的 std::unordered_set

        在左指针向右移动的时候,我们从哈希集合中移除一个字符,在右指针向右移动的时候,我们往哈希集合中添加一个字符。

由上面想法可以写出下面代码(个人走的弯路,不想看可以跳过)

class Solution {
public:int lengthOfLongestSubstring(string s) {unordered_set<char> str;int right=0;//右值针int lenght=0;//最大长度for(int i=0;i<s.size();i++){str.insert(s[i]);right=i+1;while(!str.count(s[right])&&right<s.size()){str.insert(s[right]);++right;}lenght=max(lenght,right-i);right=i;str.clear();}return lenght;}
};

可以解出来,但是耗时太长没有利用好滑动窗口减少比对次数

        我们继续优化,减少比对次数,实际上每次左值针更新时,右指针可以不用左值针处开始比较,可以先将左值针移动向里收缩,右指针不动。

        原因:假设我们选择字符串中的第 k 个字符作为起始位置,并且得到了不包含重复字符的最长子串的结束位置为 rk​。那么当我们选择第 k+1个字符作为起始位置时,首先从 k+1到 rk的字符显然是不重复的,并且由于少了原本的第 k 个字符,我们可以尝试继续增大 rk (而不是从左值针处开始),直到右侧出现了重复字符为止。

优化代码:

class Solution {
public:int lengthOfLongestSubstring(string s) {unordered_set<char> str;int right=0;//右值针int lenght=0;//最大长度for(int i=0;i<s.size();i++){if(i!=0){str.erase(s[i-1]);}while(!str.count(s[right])&&right<s.size()){str.insert(s[right]);++right;}lenght=max(lenght,right-i);}return lenght;}
};

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

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

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

示例 1:

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

思路:用滑动窗口在S中找到和p的异位词就行,滑动过程中维持滑动窗口的长度等于P的长度。

PS:这里开始我用49. 字母异位词分组同样的方法,利用排序找出p字符串和滑动窗口的key,再进行比较,发现力扣有些变态测试用例会严重超时。其他测试用例都可以通过。代码如下(仅供参考):

class Solution {
public:vector<int> findAnagrams(string s, string p) {vector<int> nums;sort(p.begin(),p.end());int left=0,right=p.size();while((left+right)<=s.size()){string result=s.substr(left,right);sort(result.begin(),result.end());if(result==p){nums.emplace_back(left);}++left;}return nums;}
};

继续优化,耗时的原因就是排序,所以换成通过统计滑动窗口中字母出现的次数来判断是否和P是异位词。最后一个小细节,如果字符串s的长度小于字符串p的长度,直接返回空。

代码:

class Solution {
public:vector<int> findAnagrams(string s, string p) {int sL=s.size(),pL=p.size();if(sL<pL){//匹配字符串没有异位词长度大return vector<int>();}vector<int> nums;vector<int> snums(26);vector<int> pnums(26);for (int i = 0; i < pL; ++i) {//统计滑动窗口刚开始,内部包含的字母数量,相当于初始化滑动窗口++snums[s[i] - 'a'];++pnums[p[i] - 'a'];}if (snums == pnums) {nums.emplace_back(0);//如果滑动窗口启动时就匹配,说明位置0就是一个答案}for (int i = 0; i < sL - pL; ++i) {--snums[s[i] - 'a'];//滑动窗口左侧抛出++snums[s[i + pL] - 'a'];//滑动窗口右侧加入if (snums == pnums) {nums.emplace_back(i + 1);//注意i位置是被抛出滑动窗口的,匹配成功应该记录i的下一个位置}}return nums;}
};

560. 和为 K 的子数组

给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 

子数组是数组中元素的连续非空序列。

示例 1:

输入:nums = [1,1,1], k = 2
输出:2

示例 2:

输入:nums = [1,2,3], k = 3
输出:2

思路:注意这里子数组是连续的序列,所以不存在跳着组合加起来等于k。看到连续数组和就用前缀和去处理(前缀和不在这里介绍)。

前缀和数组中有两种情况,一是本身就等于k,二是存在两个前缀和相减等于k。

对于上述两种情况,需要用map数组去统计前缀和出现的次数

为什么呢?

首先对于情况一,直接输出等于k的前缀和出现的次数,所以遍历前缀和时用map去统计出现次数;

对于情况二,我们举一个例子,如下 

可以看到对于情况二,如果前缀和出现相等时,那么符合条件的子数组个数就等于该前缀和出现的次数。例如前缀和0出现次数等于2,所以符合结果的子数组次数也是2,到这里就可以发现为什么要用map统计前缀和出现的次数,用代码表示就是

sum//当前前缀和
sum-k//符合条件的前缀和
map.count(sum-k)//map中符合条件的前缀和是否出现
res+=map[sum-k];//统计map中符合条件的前缀和出现次数

最后整合情况一和情况二,对于情况一来说前缀和sum等于K,所以我们初始化时候,map[0]=1,这样只要符合前缀和出现时候,map[sum-k]就是map[0]出现次数,这样就将情况一和情况二整合了。

代码:

class Solution {
public:int subarraySum(vector<int>& nums, int k) {unordered_map<int,int> map;//存放前缀和int sum=0;//当前前缀和int res=0;map[0]=1;for(auto n:nums){sum+=n;//计算前缀和if(map.count(sum-k)){res+=map[sum-k];}map[sum]++;//当前前缀和次数加一}return res;}
};


http://www.mrgr.cn/p/44127423

相关文章

WebSocket的原理、作用、API、常见注解和生命周期的简单介绍,附带SpringBoot示例

文章目录 原理作用客户端 API服务端 API生命周期常见注解SpringBoot示例 WebSocket是一种 通信协议 &#xff0c;它在 客户端和服务器之间建立了一个双向通信的网络连接 。WebSocket是一种基于TCP连接上进行 全双工通信 的 协议 。 WebSocket允许客户端和服务器在 单个TCP连接上…

怎样用PHP语言实现远程控制三路开关

怎样用PHP语言实现远程控制三路开关呢&#xff1f; 本文描述了使用PHP语言调用HTTP接口&#xff0c;实现控制三路开关&#xff0c;三路开关可控制三路照明、排风扇等电器。 可选用产品&#xff1a;可根据实际场景需求&#xff0c;选择对应的规格 序号设备名称厂商1智能WiFi墙…

【提示学习论文】BlackVIP: Black-Box Visual Prompting for Robust Transfer Learning论文原理

BlackVIP: Black-Box Visual Prompting for Robust Transfer Learning BlackVIP:稳健迁移学习的黑盒视觉提示 问题 黑盒白盒&#xff1f; 黑盒和白盒的概念与对预训练模型内部参数的了解程度相关。黑盒指的是对预训练模型的参数和结构缺乏详细了解&#xff0c;通常只能通过使…

python爬虫小案例——汽车之家

本篇文章是使用bs4中的BeautifulSoup和requests解析网页和获取数据&#x1f451;&#x1f31f; 文章目录 &#x1f31f;前言一、&#x1f349;bs4中的BeautifulSoup二、&#x1f349;bs4的语法三、&#x1f349;内容实践1. 确定想要爬取的内容2. 分析网页3. 获取数据分析 &…

三、CPU基础-缓存

计算机中缓存一般分为两个部分 1.内存 2.CPU Cache 一、CPU Cache分级 CPU Cache 通常分为大小不等的三级缓存&#xff0c;分别是 L1 Cache、L2 Cache 和 L3 Cache。 L1 Cache 和 L2 Cache 都是每个 CPU 核心独有的&#xff08;通常会分为「数据缓存」和「指令缓存」&#…

QA测试开发工程师面试题满分问答20: 软件的安全性应从哪几个方面去测试?

软件的安全性测试应从多个方面进行&#xff0c;并确保覆盖以下关键方面&#xff1a; 当回答问题时&#xff0c;可以根据自己的经验和知识&#xff0c;从上述要点中选择适合的方面进行详细说明。强调测试的综合性、全面性和持续性&#xff0c;并强调测试的重要性以及如何与开发团…

政安晨:【Keras机器学习示例演绎】(七)—— 利用 NeRF 进行 3D 体积渲染

目录 简介 设置 下载并加载数据 NeRF 模型 训练 可视化训练步骤 推理 渲染三维场景 可视化视频 结论 政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: TensorFlow与Keras机器学习实战 希望政安晨的博客能够对您有所裨益&#xff0…

01-服务与服务间的通信

这里是极简版&#xff0c;仅用作记录 概述 前端和后端可以使用axios等进行http请求 服务和服务之间也是可以进行http请求的spring封装的RestTemplate可以进行请求 用法 使用bean注解进行依赖注入 在需要的地方&#xff0c;自动注入RestTemplate进行服务和服务之间的通信 注…

制造数字化“管理套路”

在当今竞争激烈的市场环境中&#xff0c;制造企业始终关心三个核心问题&#xff1a;生产效率、产品质量、成本控制&#xff0c;所以许多企业渴望加强对生产过程的管理控制。 生产过程是一个相对复杂的过程&#xff0c;涉及到多个环节和因素。从原材料的采购到产品的设计、生产…

Nginx莫名奇妙返回了404

描述 nginx作为反向代理&#xff0c;代理python的服务&#xff0c;但是通过代理访问服务的时候&#xff0c;报了404的错误。 难受的是客户现场没有查看日志的权限&#xff0c;只有查看配置文件的权限&#xff0c;我们检测了几遍配置文件也没有找到问题&#xff0c;哎~ 问题引…

idea中打印日志不会乱码,但是部署到外部tomcat中乱码了。

问题&#xff1a;如图Tomcat乱码&#xff0c;而且启动时的系统日志不会乱码&#xff0c;webapp中的打印日志才乱码。 idea中的情况如下&#xff1a;正常中文展示。 问题分析&#xff1a;网上分析的原因是Tomcat配置的字符集和web应用的字符集不匹配&#xff0c;网上集中的解决…

233 基于matlab的多通道非负矩阵分解(MNMF)算法

基于matlab的多通道非负矩阵分解&#xff08;MNMF&#xff09;算法。其能够寻找到一个非负矩阵W和一个非负矩阵H&#xff0c;满足条件VW*H,从而将一个非负的矩阵分解为左右两个非负矩阵的乘积。使用EM准则对混合信号进行分解。程序已调通&#xff0c;可直接运行。 233 多通道非…

SpringBoot+Vue开发记录(四)

说明&#xff1a; 本篇文章的主要内容是软件架构以及项目的前端Vue创建 一、软件架构 我道听途说的&#xff0c;听说这个东西很关键很重要什么的。 软件架构&#xff08;software architecture&#xff09;是一个系统的草图,是一系列相关的抽象模式&#xff0c;用于指导大型软…

汇智知了堂晨会聚焦:NAS应用如何赋能网络安全实战

在近期汇智知了堂网络安全75班的晨会上&#xff0c;一场关于NAS应用的深入分享完美展开。学员们以饱满的热情投入到这场安全讨论中&#xff0c;共同探索网络安全的新天地。 此次分享会聚焦于NAS的应用&#xff0c;旨在帮助学员们更好地了解NAS的定义与功能&#xff0c;掌握其在…

05节-51单片机-模块化编程

1.两种编程方式的对比 传统方式编程&#xff1a; 所有的函数均放在main.c里&#xff0c;若使用的模块比较多&#xff0c;则一个文件内会有很多的代码&#xff0c;不利于代码的组织和管理&#xff0c;而且很影响编程者的思路 模块化编程&#xff1a; 把各个模块的代码放在不同的…

【微服务】spring读取配置文件多种方式深入详解

目录 一、前言 二、java配置文件介绍 2.1 java配置文件产生原因 2.2 项目使用配置文件好处 2.3 springboot项目配置文件的必要性 2.4 微服务架构下配置文件使用场景 三、java读取配置文件常用方法 3.1 使用Properties类读取配置文件 3.1.1 使用getResourceAsStream读取…

STM32 USB虚拟串口

电路原理图 usb部分 晶振部分 usb与单片机连接 配置信息 sys配置信息 rcc配置信息 usb配置信息 虚拟串口配置信息 时钟配置信息 项目配置信息 代码 包含文件 主函数代码 实验效果 修改接收波特率依然可以正常接收&#xff0c;也就是说单片机可以自动适应上位机的波特率设置。…

Linux 深入理解Linux文件系统与日志分析

在Linux系统中&#xff0c;文件名和文件数据是分开存储的 文件数据包含 元信息(即不包含文件名的文件属性) 和 实际数据 文件元信息存储在 inode(索引节点)里&#xff0c; 文件实际数据存储在 block(块)里; 文件名存储在目录块里 查看文件的元信息 stat 文件名 [ro…

HDFS详解(Hadoop)

Hadoop 分布式文件系统&#xff08;Hadoop Distributed File System&#xff0c;HDFS&#xff09;是 Apache Hadoop 生态系统的核心组件之一&#xff0c;它是设计用于存储大规模数据集并运行在廉价硬件上的分布式文件系统。 1. 分布式存储&#xff1a; HDFS 将文件分割成若干块…

【AI开发:音频】二、GPT-SoVITS使用方法和过程中出现的问题(GPU版)

1.FileNotFoundError: [Errno 2] No such file or directory: logs/guanshenxxx/2-name2text-0.txt 这个问题中包含了两个&#xff1a; 第一个&#xff1a;No module named pyopenjtalk 我的电脑出现的就是这个 解决&#xff1a;pip install pyopenjtalk 第二个&#xff1a…