哈希算法题目:字符串的排列
字数 941 2025-10-27 11:27:25
哈希算法题目:字符串的排列
题目描述:给定两个字符串 s1 和 s2,判断 s2 是否包含 s1 的排列。如果是,返回 true;否则,返回 false。换句话说,第一个字符串的排列之一是第二个字符串的子串。
解题过程:
-
问题理解
我们需要判断s2中是否包含一个子串,这个子串是s1的某个排列。这意味着这个子串和s1包含完全相同的字符,且每个字符的出现次数也相同,只是顺序可能不同。 -
核心思路
使用滑动窗口配合哈希表(字符频率统计)来解决:
- 统计s1中每个字符的出现频率
- 在s2上维护一个与s1长度相同的滑动窗口
- 统计窗口中每个字符的出现频率
- 比较两个频率统计是否相同
- 详细步骤
步骤1:特殊情况处理
如果s1的长度大于s2,s2不可能包含s1的排列,直接返回false。
步骤2:初始化频率数组
创建两个大小为26的数组(假设只包含小写字母):
- s1Count:记录s1中每个字符的频率
- s2Count:记录s2当前窗口中每个字符的频率
步骤3:统计初始频率
首先统计s1所有字符的频率,同时统计s2前n个字符的频率(n为s1的长度)。
步骤4:比较初始窗口
比较s1Count和s2Count是否完全相同。如果相同,说明找到排列,返回true。
步骤5:滑动窗口遍历
从位置n开始遍历s2的剩余部分:
- 移除窗口最左边的字符(索引为i-n)
- 添加新进入窗口的字符(索引为i)
- 每次滑动后比较两个频率数组
步骤6:优化比较
为了避免每次都比较整个数组,可以维护一个匹配计数器,记录当前有多少个字符的频率是匹配的。
- 具体实现示例
以s1 = "ab", s2 = "eidbaooo"为例:
初始化:
- s1Count: a→1, b→1, 其他→0
- 初始窗口"ei":e→1, i→1, 其他→0
- 匹配字符数:0(没有字符频率匹配)
滑动过程:
窗口1:"ei" → 不匹配
窗口2:"id" → 不匹配
窗口3:"db" → 不匹配
窗口4:"ba" → a→1, b→1,与s1Count完全匹配,返回true
- 算法复杂度
- 时间复杂度:O(n),其中n是s2的长度
- 空间复杂度:O(1),因为使用固定大小的数组
这种方法通过滑动窗口和频率统计,高效地解决了字符串排列的检测问题。