当前位置: 首页 > news >正文

leetcode_438 找到字符串中的所有异位词

1. 题意

给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,

返回这些子串的起始索引。不考虑答案输出的顺序。

异位词的意思是两个字符串的所有字符种类相同,各个种类对应的

数量相同,顺序可以不相同。

比如aabbcaabbcaabbcababcababcababc就是异位词。

2. 题解

这是一个典型的滑动窗口的问题,我们需要计算字符串sss中每个

p.size()p.size()p.size()大小的窗口内的字符串与sss是否是异位词。

2.1 定长滑动窗口+两个哈希表

用一个哈希表存ppp中各个字符的次数,用另一个哈希表存sss的当前滑窗

中字符出现的次数。如果两个哈希表各个次数相等,说明当前窗口内的

字符串是ppp的一个异位词。

窗口左端出窗口,窗口右端进入新的元素。重复处理直到遍历完sss

class Solution {
public:vector<int> findAnagrams(string s, string p) {int n = s.size();int plen = p.size();unordered_map<int,int> cur;unordered_map<int,int> tar;vector<int> ans;for (auto c: p)tar[c]++;for (int i = 0; i < n; ++i) {if ( i >= plen )cur[s[i - plen]]--;cur[s[i]]++;if (i >= plen - 1) {bool eq = true;for (auto &[k,v]: tar) {if ( cur[k] != v ) {eq = false;break;}}if (eq) {ans.push_back( i + 1 - plen );}}}return ans;}
};

可以用std::array<int,26>std::array<int,26>std::array<int,26>来代替,而且可以直接判断相等。

class Solution {
public:vector<int> findAnagrams(string s, string p) {vector<int> ans;array<int,26> cnt1;array<int,26> cnt2;for (auto c: p) {cnt1[c - 'a']++;}   int n = s.size();for (int i = 0; i < n; ++i) {cnt2[ s[i] - 'a']++;if ( i >= p.size())cnt2[ s[i - p.size()] - 'a']--;if ( cnt1 == cnt2)ans.push_back( i + 1 - p.size() );}return ans;}
};
2.2 定长滑动窗口+一个哈希表

我们用哈希表来记录当前窗口内字符串字符和ppp内字符串的差值。

diffdiffdiff表示有几种字符还不相同。

对于左端出窗口的字符串来说,

cnt[s[l]]−−cnt[s[l]]--cnt[s[l]]

如果cnt[s[l]]==1cnt[s[l]] == 1cnt[s[l]]==1

说明刚好多了一个这种字符,它出去了说明有一种字符就相同了,

因此diff++diff++diff++

如果cnt[s[l]]==0cnt[s[l]]==0cnt[s[l]]==0

说明这种字符本来是数量一致的,它出窗口了有一种字符就对不上了,

因此diff−−diff--diff

对于窗口右端的字符来说,

cnt[s[r]]++cnt[s[r]]++cnt[s[r]]++

如果cnt[s[r]]==−1cnt[s[r]] == -1cnt[s[r]]==1

说明新的元素刚好填上一种字符的缺口,因此diff−−diff--diff

如果cnt[s[r]]==0cnt[s[r]]==0cnt[s[r]]==0

说明新元素就多余了,因此diff++diff++diff++

class Solution {
public:vector<int> findAnagrams(string s, string p) {if ( s.size() < p.size()) {return vector<int>();}int n = s.size();int plen = p.size();vector<int> ans;vector<int> cnt(26, 0);for (int i = 0; i < plen; ++i) {++cnt[s[i] - 'a'];--cnt[p[i] - 'a'];}int diff = 0;for (int i = 0; i < 26; ++i) {if ( 0 != cnt[i])++diff;}if ( 0 == diff )ans.push_back( 0 );for (int i = plen; i < n; ++i) {int l = s[i - plen] - 'a';if ( cnt[ l ] == 1) {--diff;}else if ( cnt[ l ] == 0) {++diff;}--cnt[ l ];int r = s[i] - 'a';if ( cnt[r] == -1 ) {--diff;}else if ( cnt[r] == 0 ) {++diff;}++cnt[ r ];if ( diff == 0) {ans.push_back( i + 1 - plen);}}return ans;}
};
2.3 不定滑窗

我们枚举字符串s′s's的右端点,

使得它满足s′s's中所有的字符个数是小于等于sss中的所有的字符个数的。

当一个新元素进入滑窗后使得这个性质改变了,那么就不断窗口左端,

使得窗口满足这个性质。满足这个性质后我们再判断窗口长度是否等于

p.size()p.size()p.size(),长度相等也就说明了两个字符串是异位词,

将之放入答案序列。

class Solution {
public:vector<int> findAnagrams(string s, string p) {vector<int> ans;array<int,26> cnt;for (auto c: p) {cnt[c - 'a']++;}   int n = s.size();int l = 0;for (int r = 0; r < n; ++r) {int v = s[r] - 'a';cnt[ v ]--;while ( cnt[v] < 0) {++cnt[ s[l] - 'a'];++l;}if ( r - l + 1 == p.size()) {ans.push_back(  l );}}return ans;}
};

3. 参考

0x3f
leetcode

http://www.dtcms.com/a/336419.html

相关文章:

  • 代码随想录刷题Day34
  • 上位机知识篇---静态库
  • 计算机网络 TCP 延迟确认机制
  • SpringCloud 01 分布式系统
  • 自由学习记录(85)
  • 【k8s、docker】Headless Service(无头服务)
  • 如何提高目标检测模型在小目标检测任务上的性能
  • 海洋牧场助力可持续发展,保护海洋生态平衡
  • CF2121A Letter Home
  • python pandas库 series如何使用
  • DNS总结
  • JDK21 虚拟线程详解【结合源码分析】
  • 弹性布局 Flexbox
  • BEVFusion(2022-2023年)版本中文翻译解读+相关命令
  • Java项目架构设计:模块化、分层架构的实战经验
  • Linux(十六)——top命令详解
  • wrap go as a telnet client lib for c to implement a simple telnet client
  • 堆的实际应用场景
  • 【Virtual Globe 渲染技术笔记】8 顶点变换精度
  • C11期作业17(07.05)
  • Microsoft WebView2
  • AMBA-AXI and ACE协议详解(十)
  • Rust:DLL 输出对象的生命周期管理
  • 影刀初级B级考试大题2
  • STM32CUBEMX配置stm32工程
  • Linux学习-多任务(线程)
  • LangChain4j
  • 三分钟在VMware虚拟机安装winXP教程,开箱即用
  • HTTP0.9/1.0/1.1/2.0
  • linux下timerfd和posix timer为什么存在较大的抖动?