题目:
给定一个赎金信 (ransom) 字符串和一个杂志(magazine)字符串,判断第一个字符串 ransom 能不能由第二个字符串 magazines 里面的字符构成。如果可以构成,返回 true ;否则返回 false。
(题目说明:为了不暴露赎金信字迹,要从杂志上搜索各个需要的字母,组成单词来表达意思。杂志字符串中的每个字符只能在赎金信字符串中使用一次。)
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
/* 本题有两种思路:
1、暴力解法,两层for循环,但是因为题目要求不能重复使用 magazine中的字符,因此,每查到一个就需要删除一个,这样最后通过判断magazine1是否为空,判定结果
2、哈希解法,但是使用map数组的话,空间消耗太大,因此考虑使用数组来实现哈希解法*/
// 第一种:暴力解法
/* 这里使用迭代器来进行循环不知道为什么出错了,还是换回下标运算吧
第一:str.end()迭代器是const类型的,不能进行自增自减的操作
第二:遍历时,慎用迭代器,还是老老实实用下标,因为解引用迭代器时,如果对应的为空,就会报错;*/
// // for(auto a=magazine.begin();a!=(magazine.end()--);a++)
// // {
// // for(auto b=ransomNote.begin();b!=(ransomNote.end()--);b++)
// // {
// // if(*a==*b)
// // {
// // // 删除操作erase()函数需要用到迭代器来访问具体的
// // magazine.erase(b);
// // break;
// // }
// // }
// // }
// // 使用下标来进行遍历
// for(int i=0;i<magazine.size();i++)
// {
// for(int j=0;j<ransomNote.size();j++)
// {
// if(ransomNote[j]==magazine[i])
// {
// ransomNote.erase(ransomNote.begin()+j);
// break;
// }
// }
// }
// if(ransomNote.empty())
// {
// return true;
// }
// return false;
//
// // 第二种:使用数组完成哈希解法
// // 自己解的,先遍历ransomNote,在遍历magazine
// // 要注意最后的条件
// int result[26]={0};
// int count=0;
// for(int j=0;j<ransomNote.size();j++)
// {
// result[ransomNote[j]-'a']++;
// }
// for(int i=0;i<magazine.size();i++)
// {
// // magazine[i]-'a' 这个就得到了第i个元素是26个字母中的第几个;
// // 然后再对应位置上+1
// result[magazine[i]-'a']--;
// }
// for(int k=0;k<26;k++)
// {
// if(result[k]>0)
// {
// count++;
// }
// }
// if(count==0)
// {
// return true;
// }
// return false;
//
// Carl 大神 先遍历magazine ,在遍历ransomNote
int record [26]={0};
for(int i=0;i<magazine.size();i++)
{
record[magazine[i]-'a']++;
}
for(int j=0;j<ransomNote.size();j++)
{
record[ransomNote[j]-'a']--;
if(record[ransomNote[j]-'a'] < 0)
{
return false;
}
}
return true;
}
};