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

算法014——找到字符串中所有字母异位词

力扣——找到字符串中所有字母异位词(点击跳转)
在这里插入图片描述
如果 P = “abc”,那么下图中的都是它的异位词。
在这里插入图片描述
在 S 中找到 P 的异位词后,要返回起始位置的下标。
在这里插入图片描述

做这道题之前,我们要知道如何判断两个字符串是否是异位词,其实我们可以统计每个字符出现的次数,如果两个字符串中每个字符出现的次数相等,那么他们就是异位词。利用哈希表即可
在这里插入图片描述
我们定义一个变量 m 表示 p 字符串的长度,我们将 p 字符串中字母出现的次数存放在 hash1 中,在 s 这个字符串中,找到长度为 m 的子串 ,将次数存放到 hash2 中,然后比较两个哈希表是否相等就可以。
在这里插入图片描述
其实我们没有必要每次都将 m 个字母的次数都存放在哈希表中 ,如下图所示,红色为第一次枚举放入到哈希表中,粉色为第二次枚举放入到哈希表中,被荧光笔涂到的区域其实已经在哈希表中了,没必要再次存放,只需要将 c 从哈希表中删除,在将 e 添加到哈希表中即可
在这里插入图片描述
所以,我们可以使用滑动窗口的方法来解决此问题。
在这里插入图片描述

  1. left = 0,right = 0
  2. 进窗口:hash2[in]++
  3. 判断:right - left + 1 > m
    出窗口:hash2[out]–
    更新结果 :check(hash1,hash2)(比较两个哈希表是否相等)

在更新结果当中,我们需要遍历两个哈希表来进行check,比较麻烦,所以我们对更新结果的判断条件进行优化。

我们定义一个变量 count 来统计窗口有效字符的个数

如下图所示,当 c 进入窗口之后,与 hash1 中 c 字符出现的次数比较,有两种清情况。

  1. 小于等于 hash1 中的……,说明 c 为有效字符,让 count + 1
    在这里插入图片描述
    之后 right 继续右移,然后放入到 hash2 中
  2. 大于 hash1 中的……,count 不更新
    在这里插入图片描述
    接下来,right 右移
    在这里插入图片描述
    right 继续右移
    在这里插入图片描述

此时,窗口大于 m ,让 left 右移,再将第一个 c 从 hash2 中删除之前,我们要先判断此时这个字符出现的次数是否大于 hash1 中的次数,这种情况,显然是大于,那么删掉的就是无效字符,count 不需要变化,此时 c 的个数变成了 1。
在这里插入图片描述
然后我们再判断 count是否等于m,此时count == m,那么窗口中的字符就是 p 的异位词,输出起始位置下标
在这里插入图片描述
接下来的遍历就省略了

  1. 进窗口:hash2[in] <= hash1[in] ——> count++
  2. 出窗口:hash2[out] <= hash1[out] ——> count–
  3. 更新结果:count==m

代码如下:

class Solution {
    public List<Integer> findAnagrams(String s, String p) {
        List<Integer> ret = new ArrayList<Integer>();
        char[] s1 = s.toCharArray();
        char[] p1 = p.toCharArray();
        int[] hash1 = new int[26];
        for(char ch : p1){
            hash1[ch - 'a']++;
        }
        int[] hash2 = new int[26];
        int m = p.length();
        for(int left = 0,right = 0,count = 0;right < s1.length;right++){
            char in = s1[right];
            if(++hash2[in - 'a'] <= hash1[in - 'a']){
                count++;
            }
            if(right - left + 1 > m){
                char out = s1[left++];
                if(hash2[out - 'a']-- <= hash1[out - 'a']){
                    count--;
                }
            }
            if(count == m){
                ret.add(left);
            }
        }
        return ret;
    }
}

今日任务完成,嘻嘻
在这里插入图片描述

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

相关文章:

  • C++|构造函数和析构函数
  • 基于PHP的网店进销存管理系统(源码+lw+部署文档+讲解),源码可白嫖!
  • 练习-依依的询问最小值(前缀和差分)
  • C语言之链表
  • NocoBase 本周更新汇总:双因素身份认证(2FA)
  • HTML 字符集
  • Kubernetes的组成和架构
  • 一个简单的 **猜数字游戏** 的 C 语言例程
  • Java 用循环嵌套语句生成*三角形阵列
  • Vue3组件+leaflet,实现重叠marker的Popup切换显示
  • 51单片机的工作过程
  • Vue-Router:构建单页面应用的路由管理利器
  • 向量数据库技术系列四-FAISS介绍
  • three.js解决非全屏射线位置错误问题
  • 第三章:大模型中的提示学习
  • 蓝桥杯备考:图论之Prim算法
  • 2.3 滑动窗口专题:最大连续1的个数 III(LeetCode 1004)
  • PostgreSQL技术大讲堂 - 第82讲,主题:数据安全利器--密码安全策略构建
  • SpringBoot 和vue前后端配合开发网页拼图10关游戏源码技术分享
  • c++图论(一)之图论的起源和图的概念
  • 易语言模拟真人鼠标轨迹算法
  • 2025年渗透测试面试题总结-某四字大厂实习面试复盘 一面 三面(题目+回答)
  • Amazon Quantum Ledger Database (QLDB):革新数据可信记录的终极解决方案
  • (C语言)写一个递归函数DigitSum(n),输入一个非负整数,返回组成它的数字之和(递归函数)
  • Axure设计之下拉多选框制作教程B(中继器)
  • 【Aioredis实战总结】Aioredis简介
  • 详解Flutter单线程模型,以及Flutter是如何通过单线程实现异步的
  • Go语言os标准库
  • SSA-随机森林分类预测matlab代码
  • 【Linux】https 协议