leetcode[438][medium]找到字符串中所有字母异位词

 目录

题目

思路

答案


一、题目

给定两个字符串 s 和 p,找到 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 仅包含小写字母

二、思路

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

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

[i, i+p.length()-1]表示滑动窗口的下标,其中 0 <= i <= (s的长度-p的长度+1)。用数组统计完滑动窗口内的词频后,通过Arrays.equals方法与目标字符串 p 的词频做比较。如果相等,则 i 即为满足条件的下标。

窗口向后移动一位,新的窗口下标为[i+1 , i+p.length()]。统计新滑动窗口内的词频时,可以在上一步统计结果的基础上,加上新移入窗口的下标为 i+p.length()的字符,并去掉移出窗口的下标为 i 的字符,以此来降低时间复杂度。

三、答案

import java.util.Arrays;

class Solution {
    public List<Integer> findAnagrams(String s, String p) {
        List<Integer> indexList = new ArrayList<>();
        // 统计目标字符串的词频
        int[] target = new int[26];
        for (int i = 0; i < p.length(); i++) {
            target[p.charAt(i) - 'a']++;
        }
        // 统计滑动窗口字符串的词频
        int[] window = new int[26];
        for (int i = 0; i <= s.length() - p.length(); i++) {
            // [i, i+p.length()-1]表示滑动窗口的下标
            if (i == 0) {
                for (int j = i; j < i + p.length(); j++) {
                    window[s.charAt(j) - 'a']++;
                }
            } else {
                //更新词频:下标i - 1移出窗口,i + p.length() - 1移入窗口
                window[s.charAt(i - 1) - 'a']--;
                window[s.charAt(i + p.length() - 1) - 'a']++;
            }
            if (Arrays.equals(target, window)) {
                indexList.add(i);
            }
        }
        return indexList;
    }
}


日日刷算法,老年痴呆远离我~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值