leetcode
leetcode 2901 ~ 2950
找到字符串中所有字母异位词

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

难度:

标签:

题目描述

English description is not available for the problem. Please switch to Chinese.

代码结果

运行时间: 47 ms, 内存: 16.6 MB


// 思路:
// 使用滑动窗口和Java Stream来寻找s中所有p的变位词的子串。
// 1. 计算p中每个字符的出现次数,存储在一个计数数组中。
// 2. 初始化一个窗口,窗口大小为p的长度,并计算窗口中每个字符的出现次数。
// 3. 滑动窗口,每次移动一个字符,并更新窗口中字符的计数。
// 4. 如果窗口中的字符计数与p中的字符计数匹配,则记录起始索引。

import java.util.*;
import java.util.stream.*;

public class Solution {
    public List<Integer> findAnagrams(String s, String p) {
        if (s == null || p == null || s.length() < p.length()) return Collections.emptyList();

        int[] pCount = new int[26];
        int[] sCount = new int[26];
        for (char c : p.toCharArray()) {
            pCount[c - 'a']++;
        }

        return IntStream.range(0, s.length())
            .mapToObj(i -> {
                sCount[s.charAt(i) - 'a']++;
                if (i >= p.length()) {
                    sCount[s.charAt(i - p.length()) - 'a']--;
                }
                return matches(pCount, sCount) ? i - p.length() + 1 : -1;
            })
            .filter(index -> index != -1)
            .collect(Collectors.toList());
    }

    private boolean matches(int[] pCount, int[] sCount) {
        return IntStream.range(0, 26).allMatch(i -> pCount[i] == sCount[i]);
    }
}

解释

方法:

此题解采用滑动窗口和字符频率计数的方法来找出所有的字母异位词的起始索引。首先,如果字符串p的长度大于s,则直接返回空列表,因为s中不可能有p的异位词。然后,使用两个大小为26的数组cnt_s和cnt_p来统计窗口内s的字符频率和字符串p的字符频率。初始窗口大小为p的长度,逐一比较两个计数数组,如果相等,则将当前窗口的起始索引加入结果列表。随后,窗口向右滑动,每次移动更新窗口内的字符频率,继续比较和记录结果。

时间复杂度:

O(m)

空间复杂度:

O(1)

代码细节讲解

🦆
题解中提到使用两个大小为26的数组来统计字符频率,为什么选择数组而不是其他数据结构,例如哈希表?
在这种场景下,由于只涉及小写英文字母(a到z),我们可以直接使用一个固定大小为26的数组来映射每个字母的频率,其中数组的索引(0到25)直接对应字母'a'到'z'。使用数组的好处包括:1. 访问速度快,数组的访问时间复杂度为O(1);2. 内存使用更高效,因为数组不需要额外的存储空间来维护键和结构本身;3. 实现简单,易于通过简单的算术运算(ord(char) - ord('a'))计算索引。而使用哈希表虽然灵活且可以应对更广泛的字符类型,但在这个特定问题中,它带来的额外内存和可能的较慢访问速度并不是必须的。
🦆
在滑动窗口中,每次向右移动窗口时只更新一个字符的进入和离开,这种方法有效率提升的原理是什么?
滑动窗口算法通过每次只更新进入和离开窗口的字符来减少不必要的计算。具体来说,在这个题解中,当窗口向右滑动时,只需要做两件事:增加新字符的频率计数,减少离开字符的频率计数。这种方法相比重新计算整个窗口的字符频率更高效,因为它避免了每次窗口移动时对所有字符进行全面重新计数的开销,大大减少了计算量。这使得时间复杂度降低,特别是在字符串s较长时,效率提升尤为明显。
🦆
如果输入字符串s包含非小写字母的字符,现有的解决方案还适用吗?
现有的解决方案假设输入字符串仅包含小写英文字母,因此直接使用大小为26的数组来记录字符频率。如果输入字符串s包含非小写字母的字符,这种方法将不再适用。这是因为数组的索引计算(ord(char) - ord('a'))可能会得到负值或超出25的值,导致数组越界错误。在这种情况下,我们需要使用更通用的数据结构,例如哈希表,来适应所有可能的字符。哈希表能够动态地存储和查找任何字符的频率,不受字符种类的限制。

相关问题