438. 找到字符串中所有字母异位词【我亦无他唯手熟尔】

简介: 438. 找到字符串中所有字母异位词【我亦无他唯手熟尔】

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

难度 中等

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

提示:

  • 1 <= s.length, p.length <= 3 * 104
  • s 和 p 仅包含小写字母

题解

思路:暴力
把p的全排列找出(可行性不高)
判断s里面是否包含
或者
类比:模式匹配
把p按字母升序排列得到新的p
把每次匹配的结果按字母升序排列和新的p比较,
比较可以通过异或运算
或者
把所求的p中的字母转化成一种唯一的数字(ACII码)
把所求的p转化成这些数字进行某种运算得到的唯一的结果(异或)

代码

发现不太好搞,直接看官方解答吧
并且异或不一定保证结果的唯一性

官方

方法一:滑动窗口

思路

根据题目要求,我们需要在字符串 s 寻找字符串 p 的异位词。因为字符串 p 的异位词的长度一定与字符串 p 的长度相同,所以我们可以在字符串 s 中构造一个长度为与字符串 p 的长度相同的滑动窗口,并在滑动中维护窗口中每种字母的数量;当窗口中每种字母的数量与字符串 p 中每种字母的数量相同时,则说明当前窗口为字符串 p 的异位词。

算法

在算法的实现中,我们可以使用数组来存储字符串 p 和滑动窗口中每种字母的数量。

细节

当字符串 s 的长度小于字符串 p 的长度时,字符串 s 中一定不存在字符串 p 的异位词。但是因为字符串 s 中无法构造长度与字符串 p 的长度相同的窗口,所以这种情况需要单独处理。
代码


作者:LeetCode-Solution

链接:https://leetcode-cn.com/problems/find-all-anagrams-in-a-string/solution/zhao-dao-zi-fu-chuan-zhong-suo-you-zi-mu-xzin/

来源:力扣(LeetCode)

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

class Solution {
    public List<Integer> findAnagrams(String s, String p) {
        int sLen = s.length(), pLen = p.length();
        if (sLen < pLen) {
            return new ArrayList<Integer>();
        }
        List<Integer> ans = new ArrayList<Integer>();
        int[] sCount = new int[26];
        int[] pCount = new int[26];
        for (int i = 0; i < pLen; ++i) {
            ++sCount[s.charAt(i) - 'a'];
            ++pCount[p.charAt(i) - 'a'];
        }
        if (Arrays.equals(sCount, pCount)) {
            ans.add(0);
        }
        for (int i = 0; i < sLen - pLen; ++i) {
            --sCount[s.charAt(i) - 'a'];
            ++sCount[s.charAt(i + pLen) - 'a'];
            if (Arrays.equals(sCount, pCount)) {
                ans.add(i + 1);
            }
        }
        return ans;
    }
}

解读

用一下语句进行对s和p的转换,
 for (int i = 0; i < pLen; ++i) {
            ++sCount[s.charAt(i) - 'a'];
            ++pCount[p.charAt(i) - 'a'];
        }
  把s和p都转为两个个计数器数组sCount和pCount[
  问题就转化为在sCount寻找pCount
   for (int i = 0; i < sLen - pLen; ++i) {
            --sCount[s.charAt(i) - 'a'];
            ++sCount[s.charAt(i + pLen) - 'a'];
            if (Arrays.equals(sCount, pCount)) {
                ans.add(i + 1);
            }
        }
  上面就是窗口滑动,每一次只滑动一位,然后比较

相关文章
|
12月前
|
存储 程序员 编译器
什么是内存泄漏?C++中如何检测和解决?
大家好,我是V哥。内存泄露是编程中的常见问题,可能导致程序崩溃。特别是在金三银四跳槽季,面试官常问此问题。本文将探讨内存泄露的定义、危害、检测方法及解决策略,帮助你掌握这一关键知识点。通过学习如何正确管理内存、使用智能指针和RAII原则,避免内存泄露,提升代码健壮性。同时,了解常见的内存泄露场景,如忘记释放内存、异常处理不当等,确保在面试中不被秒杀。最后,预祝大家新的一年工作顺利,涨薪多多!关注威哥爱编程,一起成为更好的程序员。
555 0
|
移动开发 JavaScript 前端开发
HTML5 表单属性详解
HTML5引入了多种新的表单属性,使表单创建与验证更加便捷高效。新增的输入类型包括`email`、`url`、`tel`等,常用属性有`placeholder`、`required`等。表单元素如`&lt;form&gt;`可设置提交方法和目标URL,`&lt;button&gt;`及`&lt;input type=&quot;submit&quot;&gt;`用于提交。新元素`&lt;datalist&gt;`和`&lt;output&gt;`提供更多功能。HTML5还提供了内置表单验证机制,增强用户体验。
|
缓存 前端开发 JavaScript
前端性能优化:实用技巧与策略
本文介绍了前端性能优化的关键技巧与策略,涵盖减少HTTP请求、利用浏览器缓存、压缩资源文件、异步加载非关键资源、优化CSS和JavaScript、减少DOM操作、谨慎使用Web字体、优化第三方脚本、使用服务工作者以及性能监测和分析等方面,帮助提升用户体验和搜索引擎优化效果。
|
算法 网络性能优化
Audio Over IP的PTP时钟初探
Audio Over IP的PTP时钟初探
248 0
|
数据采集 JSON 数据可视化
PLC 西门子s7-200 轻松数据上云
​ 在在工业场景中,经常会使用到PLC进行各种设备的数据采集和控制。本教程介绍使用海创边缘网关配置s7-200 smart跑马灯场景效果,并实现数据上传海创物联网平台和阿里云物联网,实际项目中可能更多是跟MES相关系统进行对接,但技术逻辑相同,可参考!
7463 0
|
JavaScript 前端开发
vue中设置echarts宽度自适应
vue中设置echarts宽度自适应
545 0
vue中设置echarts宽度自适应
|
大数据 数据中心 云计算
云服务器液冷架构最佳实践 阿里云多篇论文入选DesignCon 2023和ECTC 2023
云服务器液冷架构最佳实践 阿里云多篇论文入选DesignCon 2023和ECTC 2023
云服务器液冷架构最佳实践 阿里云多篇论文入选DesignCon 2023和ECTC 2023
|
存储 网络协议 安全
网络知识大集合(最详细)与网络通信过程
首先 我碰到了一个问题,一个数据包从我们的电脑上,经过层层的交换机、路由器到达目标服务器的过程中,数据包会有哪些改动,是如何一步步传递过去又是如何返回回来的?
网络知识大集合(最详细)与网络通信过程
|
云安全 人工智能 弹性计算
专访阿里云技术极客,守护网络世界安全的神秘人
网络与数据时代不断催生着新的命题,对现代人来讲,如何在技术蓬勃发展的信息爆炸中寻求一席之地,是我们应该不断探索的命题。我们带着这些问题,和各个领域的杰出技术人对话,一期一会,抵掌而谈,走进他们的“技术人生”,和他们一起去寻找答案。
1743 0
专访阿里云技术极客,守护网络世界安全的神秘人