【滑动窗口:力扣438找到字符串中所有字母异位词】

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

这道题是让我们找s中所有p的异位词的字串,这里有一个新的概念"异位词",简单来说,异位词主要满足两个条件:

  • 两个单词由完全相同的字母组成(种类一致,个数一致)
  • 这些字母的排序方式不同

通过这两点我们就可以知道,互为异位词的两个字符串长度一定是相同的!因此我们可以用定长滑动窗口来做

定长滑动窗口

思路

在字符串s中维护一个滑动窗口,当窗口长度等于p.length()的时候,判断窗口内字母的种类跟个数是否等于p中字母的种类跟个数,如果满足条件,统计到答案中。

代码

java 复制代码
class Solution {
  public List<Integer> findAnagrams(String s, String p) {
    //统计 p 的每种字母的出现次数(题中说了字母只有小写字母)
    int [] cntP = new int[26];
    for(char c : p.toCharArray()) {
      cntP[c - 'a']++;
    }

    List<Integer> ans = new ArrayList<>();
    int [] cntS = new int[26];
    int n = p.length();
    int left = 0;
    for(int i = 0; i < s.length(); i++) {
      //统计s每种字母的出现次数
      cntS[s.charAt(i) - 'a']++;

      //窗口大小不够p的长度
      if(i - left + 1 < n) {
        continue;
      }

      //判断窗口内的每种字母的出现次数跟p的是否相同
      if(Arrays.equals(cntP, cntS)) {
        ans.add(left);
      }

      //移动左端点
      cntS[s.charAt(left) - 'a']--;
      left++;

    }
    return ans;
  }
}

除了这种方法,我们还可以使用不定长滑动窗口

不定长滑动窗口

思路

我们只需要枚举s子串的右端点,如果发现子串中某个字母的个数大于p中这种字母出现的次数,则缩小窗口(left右移),如果发现子串的长度等于p的长度,说明满足条件了,此时子串中每种字母的出现次数,等于 p 的每种字母的出现次数,统计到答案里面

这种方法理解的难点如下:

当子串长度跟p长度相等的时候,为什么能直接判断满足条件了,不会出现子串的其中一种字母的出现次数比 p 的小的情况吗?

不会。假设子串长度跟p的长度相等了,子串的某个字母的个数比p中这个字母的个数少,例如s是"aabbbc",p是"aabbcc"

此时子串中c的个数小于p中c的个数,但是由于长度相同,那么子串中一定有一个字母的个数大于p中这个字母的个数,这是矛盾的!

因此在"如果发现子串中某个字母的个数大于p中这种字母出现的次数,则缩小窗口"这个前提下,只要子串长度跟p的长度相等,子串中所有字母的种类和个数也都跟p中的字母种类个数相同!

代码

java 复制代码
class Solution {
  public List<Integer> findAnagrams(String s, String p) {
    //统计 p 的每种字母的出现次数(题中说了字母只有小写字母)
    int [] cntP = new int[26];
    for(char c : p.toCharArray()) {
      cntP[c - 'a']++;
    }

    List<Integer> ans = new ArrayList<>();
    int [] cntS = new int[26];
    int n = p.length();
    int left = 0;
    for(int i = 0; i < s.length(); i++) {
      //统计s每种字母的出现次数
      int c = s.charAt(i) - 'a';
      cntS[c]++;

      while(cntS[c] > cntP[c]) {
        cntS[s.charAt(left) - 'a']--;
        left++;
      }

      if(i - left + 1 == p.length()) {
        ans.add(left);
      }
    }
    return ans;
  }
}

如果这篇文章对你有帮助,欢迎点赞、评论、关注、收藏。你们的支持是我前进的动力!

相关推荐
罗西的思考1 小时前
机器人模型(WM / WAM / VLA)综合分析与对比:从「看」到「想」再到「做」
人工智能·算法·机器学习
小哈里2 小时前
【知识】从学科到实践:自然・工程・社科・人文|算法・研发・产品・品牌设计
程序人生·算法·产品·设计·工程
小π军3 小时前
最大重叠区间数量
数据结构·算法
镜像视界(浙江)科技有限公司3 小时前
《视频孪生之上:二维展示终结,三维空间计算重构城市逻辑》——跨摄像连续表达 × 三角测量厘米级定位 × 动态轨迹建模,构建新一代城市空间
大数据·人工智能·算法·矩阵·音视频·空间计算
a187927218313 小时前
【算法】双指针与滑动窗口(二):滑动窗口——吃进、判定、吐出
算法·leetcode·双指针·滑动窗口·原理·模板·算法讲解
铭哥的编程日记3 小时前
从一道 LeetCode Hard 到吃透一类题:加权区间调度「排序 + 二分 + DP」
算法·leetcode·职场和发展
Navigator_Z4 小时前
LeetCode //C - 1248. Count Number of Nice Subarrays
c语言·算法·leetcode
wzdark5 小时前
多维数组在算法设计中的存储映射问题4
算法
Phil3235 小时前
多智能体不是越多越好:Google《Towards a Science of Scaling Agent Systems》论文深度解读
算法
6Hzlia5 小时前
【Classic 150 刷题计划】 LeetCode 26. 删除有序数组中的重复项 | C++ 快慢双指针经典模板
c++·算法·leetcode