【字符串全排列】LeetCode 567. Permutation in String
Solution1:【超时,未能AC】
得到s1的所有全排列组合,然后在s2中查找s1的全排列集合
因为超时,未能AC,只是记录一下:
【注意】此题中针对字符串的全排列代码非常之经典!应当牢记!
class Solution {
public:
bool checkInclusion(string s1, string s2) {
vector<string> s1_per = permute(s1);
for(auto a : s1_per) {
if(s2.find(a) != string::npos)
return true;
}
return false;
}
vector<string> permute(string& str) {
if (str.empty()) return vector<string>(1, "");
vector<string> res;
string first(1, str[0]);
str.erase(0, 1);
vector<string> words = permute(str);
for (auto &a : words) {
for (int i = 0; i <= a.size(); ++i) {
a.insert(i, first);
res.push_back(a);
a.erase(i, 1);
}
}
return res;
}
};
Solution2:
我们先来看使用两个哈希表来做的情况,我们先来分别统计s1和s2中前n1个字符串中各个字符出现的次数,其中n1为字符串s1的长度,这样如果二者字符出现次数的情况完全相同,说明s1和s2中前n1的字符互为全排列关系,那么符合题意了,直接返回true。如果不是的话,那么我们遍历s2之后的字符,对于遍历到的字符,对应的次数加1,由于窗口的大小限定为了n1,所以每在窗口右侧加一个新字符的同时就要在窗口左侧去掉一个字符,每次都比较一下两个哈希表的情况,如果相等,说明存在,参见代码如下:
代码:
不得不说,算法真是牛逼啊。。
class Solution {
public:
bool checkInclusion(string s1, string s2) {
int n1 = s1.size(), n2 = s2.size();
vector<int> m1(128), m2(128);
for (int i = 0; i < n1; ++i) {
++m1[s1[i]]; ++m2[s2[i]];
}
if (m1 == m2) return true;
for (int i = n1; i < n2; ++i) {
++m2[s2[i]];
--m2[s2[i - n1]];
if (m1 == m2) return true;
}
return false;
}
};
20180708更:
可以!
class Solution {
public:
bool checkInclusion(string s1, string s2) {
int n1 = s1.size(), n2 = s2.size();
if (n1 > n2) return false;
vector<int> hash_s1(256, 0), hash_s2(256, 0);
for (int i = 0; i < n1; i++) {
hash_s1[s1[i]]++;
hash_s2[s2[i]]++;
}
if (hash_s1 == hash_s2) return true;
for (int i = n1; i < n2; i++) {
hash_s2[s2[i]]++;
hash_s2[s2[i-n1]]--;
if (hash_s1 == hash_s2)
return true;
}
return false;
}
};