大家好,继续刷题,已经刷到了哈希表的部分,感觉这道题还是学到了很多,记录一下。
题目要求:
思路:1.我自己想的办法很笨,最终超时了,就是把s分成一个一个子字符串,然后跟p一起sort一下,然后看一不一样。代码如下:
class Solution {
public:
vector<int> findAnagrams(string s, string p) {
vector<int> result;
int len = s.size();
int len_p = p.size();
if(len == 0)
return result;
string temp;
map<int,string> hash;
for(int i = 0;i <= len - len_p;i++){
temp = s.substr(i,len_p);
hash.insert(pair<int,string> (i,temp));
temp.clear();
}
map<int,string> :: iterator it = hash.begin();
while(it != hash.end()){
string t = it -> second;
sort(t.begin(),t.end());
sort(p.begin(),p.end());
if(t == p){
result.push_back(it -> first);
}
it++;
}
return result;
}
};
2.然后去看了其他大大们写的代码,学习了很多,其中一种思想是获取s的子字符串然后计算里面字母的个数,比较跟p的字母个数是否一样就可以了,很巧妙,但这种思想也分两种办法,一种是用map来存放子字符串和p的字母及其个数,但是后续查看是否一样还需要遍历查找啊什么的就很麻烦,还有一种是用vector来存放子字符串和p的字母及其个数,vector相比map,使用起来就很灵活,速度也更快。代码如下。
map版:
class Solution {
public:
vector<int> findAnagrams(string s, string p) {
int plen=p.size(),slen=s.size();
vector<int> res;
if(slen < plen) {return res;}
map<char,int> mp;
for(auto c:p) {
mp[c]++;
}
for(int i=0;i<slen-plen+1;i++){
map<char,int> temp;
string substri=s.substr(i,plen);
for(auto c:substri) temp[c]++;
if(mapequal(temp,mp))
res.push_back(i);
}
return res;
}
bool mapequal(map<char,int>& a,map<char,int>& b){
if(a.size()!=b.size()) return false;
map<char,int>::iterator iter;
for(iter=a.begin(); iter!=a.end(); iter++){
if(b.count(iter->first)==0||b[iter->first]!=iter->second)
return false;
}
return true;
}
};
vector版:
class Solution {
public:
vector<int> findAnagrams(string s, string p) {
vector<int> pv(26,0), sv(26,0), res;
if(s.size() < p.size())
return res;
for(int i = 0; i < p.size(); ++i)
{
++pv[p[i]-'a'];
++sv[s[i]-'a'];
}
if(pv == sv)
res.push_back(0);
for(int i = p.size(); i < s.size(); ++i)
{
++sv[s[i]-'a'];
--sv[s[i-p.size()]-'a'];
if(pv == sv)
res.push_back(i-p.size()+1);
}
return res;
}
};
学到的东西有:
1.map的遍历:
for(iter=a.begin(); iter!=a.end(); iter++){
if(b.count(iter->first)==0||b[iter->first]!=iter->second)
return false;
}
这里string::count()只是统计是否有字符,有就是返回1,无就是返回0。
2.for循环的用法:
for(auto c:s)//对于s中的每个字符
此处表示对s进行循环,c表示从0开始到len-1。
3.并不要盲目使用容器,最合适的才是最好的。
我们下期见。