本节博客是对题目——找到字符串中所有字母异位词的从读题到代码实现以及优化的详细解读,有需要借鉴即可。
1.题目
题目链接:LINK
首先来解释一下什么是异位词,所谓“异位词”,即不要求字母顺序的字符串。
其实这个题目思路很快就可以想到,拿个left,right指针,使两者间距始终等于p字符串长度,再与p字符串对比一下就行了。
说起来这个思路那不就是“滑动窗口”嘛,因为两个指针都是从左到右移动的。
那异位怎么进行比较的呢?可以搞一个哈希数组进行依次比较即可。
2.滑动窗口 + 哈希数组
于是,我们可以写出下面的代码:
class Solution { public: bool check(int* p, int*s) { for(int i = 0;i < 128;i++) { if(p[i] != s[i]) { return false; } } return true; } vector<int> findAnagrams(string s, string p) { //统计一下p字符串的字符信息 size_t len = p.size(); int hash_p[128] = {0}; for(int i = 0;i<len;i++) { hash_p[p[i]]++; } int n = s.size(); int hash_s[128] = {0}; vector<int> ret; //滑动窗口 for(int right = 0,left = 0;right < n;right++) { //进窗口 hash_s[s[right]]++; //判断,出窗口 if(right - left + 1 > len) { hash_s[s[left]]--; left++; } //更新结果 if(check(hash_p,hash_s) && right - left + 1 == len) { ret.push_back(left); } } return ret; } };
实际上,题目中明确说只有小写字母,所以说可以把哈希数组搞成26个的:
class Solution { public: bool check(int* p, int* s) { for (int i = 0; i < 26; i++) { if (p[i] != s[i]) { return false; } } return true; } vector<int> findAnagrams(string s, string p) { //统计一下p字符串的字符信息 size_t len = p.size(); int hash_p[26] = { 0 }; for (int i = 0; i < len; i++) { hash_p[p[i] - 'a']++; } int n = s.size(); int hash_s[26] = { 0 }; vector<int> ret; //滑动窗口 for (int right = 0, left = 0; right < n; right++)//"cbaebabacd" { //进窗口 hash_s[s[right] - 'a']++; //判断,出窗口 if (right - left + 1 > len) { hash_s[s[left] - 'a']--; left++; } //更新结果 if (check(hash_p, hash_s) && right - left + 1 == len) { ret.push_back(left); } } return ret; } };
3.异位词优化
虽然这样可以解题,不过问题是如果是比较的是比较多的字符呢?不仅仅是26的小写字母。我想如果这样比较,复杂度瞬间就会上来了。
所以,在比较异位词时,我们需要再优化一下:
思路大致是下面这样的,如下:
所以,可以优化为下面代码:
class Solution { public: vector<int> findAnagrams(string s, string p) { //统计一下p字符串的字符信息 size_t len = p.size(); int hash_p[26] = { 0 }; for (int i = 0; i < len; i++) { hash_p[p[i] - 'a']++; } int n = s.size(); int count = 0;//count标识有效字符的个数,即p字符串的长度 int hash_s[26] = { 0 }; vector<int> ret; //滑动窗口 for (int right = 0, left = 0; right < n; right++)//"cbaebabacd" { //进窗口 hash_s[s[right] - 'a']++; if(hash_s[s[right]-'a'] <= hash_p[s[right]-'a'])count++;//进窗口,维护有效字符个数 //判断,出窗口 if (right - left + 1 > len) { if(hash_s[s[left] - 'a'] <= hash_p[s[left] - 'a'])count--;//出窗口,维护有效字符个数 hash_s[s[left] - 'a']--; left++; } //更新结果 if (count == len) { ret.push_back(left); } } return ret; } };
4.总结
其实总结一下来看,这个题目除了异位词问题之外也没什么东西,这个题目是一个典型的“固定长度的滑动窗口”,要解出来难度不大。
EOF