leetcode:438. 找到字符串中所有字母异位词
题目
给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。
示例:
输入: s = "cbaebabacd", p = "abc"输出: [0,6]解释:起始索引等于 0 的子串是 "cba", 它是 "abc" 的异位词。起始索引等于 6 的子串是 "bac", 它是 "abc" 的异位词。
输入: s = "abab", p = "ab"输出: [0,1,2]解释:起始索引等于 0 的子串是 "ab", 它是 "ab" 的异位词。起始索引等于 1 的子串是 "ba", 它是 "ab" 的异位词。起始索引等于 2 的子串是 "ab", 它是 "ab" 的异位词。
解答 & 代码
滑动窗口,思路同:
[中等] 567. 字符串的排列
p 的字母异位词就是 p 的字母排列,一个意思。和上题唯一的区别是,在找到符合条件的窗口时,上题是直接返回 true,这里则是将左指针存入结果数组。
class Solution {public:vector<int> findAnagrams(string s, string p) {unordered_map<char, int> needs;unordered_map<char, int> window;for(int i = 0; i < p.size(); ++i)++needs[p[i]];int left = 0; // 左指针int right = 0; // 右指针int validChCnt = 0;vector<int> result;while(right < s.size()){char ch = s[right];++right;// 进行窗口内数据的更新if(needs.find(ch) != needs.end()){++window[ch];if(window[ch] == needs[ch])++validChCnt;}// cout << "window: [" << left << ", " << right << "]" << endl;// 判断左侧窗口是否要收缩while(right - left >= p.size()){// 当窗口符合条件时,将窗口起始下标加入结果数组if(validChCnt == needs.size())result.push_back(left);char deleteC = s[left];++left;// 进行窗口内数据的更新if(needs.find(deleteC) != needs.end()){if(window[deleteC] == needs[deleteC])--validChCnt;--window[deleteC];}// cout << "window: [" << left << ", " << right << "]" << endl;}}return result;}};
复杂度分析:设字符串 s 长为 N,字符串p 包含 C 个不同的字符
- 时间复杂度 O(N):最坏情况下,字符串
s的每个字符分别被左、右指针遍历一次 - 空间复杂度 O(C):两个哈希表的空间复杂度都取决于字符串
p中不同字符的种数 C
执行结果:
执行结果:通过执行用时:20 ms, 在所有 C++ 提交中击败了 28.20% 的用户内存消耗:8.3 MB, 在所有 C++ 提交中击败了 92.82% 的用户
