给定两个字符串 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 * 104s和p仅包含小写字母
解题思路
-
统计字符频率:
-
使用一个长度为 26 的数组
p_count记录字符串p中每个字符的出现次数。 -
比如,
p = "abc",则p_count = [1, 1, 1, 0, ..., 0]('a'出现 1 次,'b'出现 1 次,'c'出现 1 次)。
-
-
滑动窗口:
-
在字符串
s上滑动一个长度为len(p)的窗口,统计窗口内每个字符的出现次数。 -
使用另一个长度为 26 的数组
window_count记录当前窗口内字符的出现次数。 -
比较
window_count和p_count,如果相等,则当前窗口是一个异位词,记录窗口的起始索引。
-
写的挺狗史的,但也记录一下把
int* findAnagrams(char* s, char* p, int* returnSize)
{
int len_p = strlen(p);
int len_s = strlen(s);
*returnSize = 0; // 初始化返回地址的大小为0
// 情况1:当主串S长度小于对比串P,不可能有异位词,返回空
if(len_s<len_p)
{
return NULL;
}
// 正常情况:
// 初始化计数数组
int p_count[26]={0}; // 用于记录p中每个字符出现的次数
int window_count[26]={0}; // 记录当前窗口每个字符出现的次数
// 填充P的次数
for(int i=0; i<len_p; i++)
{
char current_char = p[i]; // 获取当前字符存到p[i]
int index = current_char - 'a'; // 字符转换为索引值
p_count[index]++; // 对应的索引值+1
}
// 预分配结果数组,最大的可能为len_s-len_p+1
int* result = (int*)malloc(sizeof(int)*(len_s-len_p+1)); // 指针自身 = (指针类型*)malloc(sizeof(指针类型)*数据数量)
if (result == NULL) // 检查是否成功分配内存,如果分配失败,返回NULL
{
*returnSize = 0;
return NULL;
}
// 窗口滑动处理
for(int i=0; i<=len_s-len_p; i++)
{
// 重置当前窗口计数
for(int k=0; k<26; k++)
{
window_count[k]=0;
}
// 填充当前窗口计数
for(int j=0; j<len_p; j++)
{
char current_char_w = s[i+j]; // 获取当前字符
int index_w = current_char_w - 'a'; // 将字符转换为索引
window_count[index_w]++;
}
// 比较当前窗口是否与p的计数匹配
int is_match = 1; // 先假设匹配
for(int k=0; k<26; k++)
{
if(p_count[k]!=window_count[k])
{
is_match = 0; // 不匹配
break;
}
}
// 如果匹配,记录起始索引
if(is_match)
{
// 将当前窗口的起始索引 i 存入结果数组
result[*returnSize] = i;
// 更新结果数组的大小,加 1
*returnSize = *returnSize + 1;
}
}
return result;
}
滑动窗口部分:
遍历长字符串S,从每个位置都扫一遍长度等于短串p的字串;重置窗口,统计当前窗口的字符频率;比较window_count和p_count,如果相等,则记录起始索引i
GPT帮忙写个模拟过程,好理解
举例:
模拟过程
输入:
s = "cbaebabacd"; p = "abc";
步骤:
-
初始化:
-
len_p = 3,len_s = 10。 -
p_count = [1, 1, 1, 0, ..., 0]('a'、'b'、'c'各出现 1 次)。
-
-
滑动窗口:
-
窗口 1:
i = 0,子串"cba"。-
window_count = [1, 1, 1, 0, ..., 0]。 -
与
p_count匹配,记录索引0。
-
-
窗口 2:
i = 1,子串"bae"。-
window_count = [1, 1, 0, 0, ..., 0]。 -
不匹配。
-
-
窗口 3:
i = 2,子串"aeb"。-
window_count = [1, 1, 0, 0, ..., 0]。 -
不匹配。
-
-
窗口 4:
i = 3,子串"eba"。-
window_count = [1, 1, 0, 0, ..., 0]。 -
不匹配。
-
-
窗口 5:
i = 4,子串"bab"。-
window_count = [0, 2, 0, 0, ..., 0]。 -
不匹配。
-
-
窗口 6:
i = 5,子串"aba"。-
window_count = [2, 1, 0, 0, ..., 0]。 -
不匹配。
-
-
窗口 7:
i = 6,子串"bac"。-
window_count = [1, 1, 1, 0, ..., 0]。 -
与
p_count匹配,记录索引6。
-
-
-
结果:
result = [0, 6]。
总结
-
滑动窗口:通过滑动窗口统计字符频率,判断是否与
p的字符频率匹配。 -
时间复杂度:O(n * m),其中
n是s的长度,m是p的长度。 -
空间复杂度:O(1),使用了固定大小的计数数组。
&spm=1001.2101.3001.5002&articleId=146382788&d=1&t=3&u=b05dea188a7f49c984099492e3062892)
1074

被折叠的 条评论
为什么被折叠?



