题目: 383. 赎金信 - 力扣(LeetCode) (leetcode-cn.com)
思路一:哈希表法
分析:
判断第一个字符串 ransom 能不能由第二个字符串 magazines 里面的字符构成。用哈希表将字符串 magazines的字符的频率统计出来,然后字符串ransomNote的字符在哈希表中出现过吗,出现过就将这个字符的频率减一;
步骤:
- 定义一个哈希表
- 用哈希表统计magazine里面的字符的频率
- 遍历ransomNote字符串每个字符,如果字符出现在哈希表中,就将哈希表中这个字符的频率减掉1,否则就返回false
- 遍历结束后,说明ransomNote在 magazines 里面 都出现过,返回true
bool canConstruct(string ransomNote, string magazine) {
unordered_map<char,int>map;
int len=magazine.size();
int size=ransomNote.size();
for(auto ch:magazine)
{
map[ch]++;
}
for(int i=0;i<size;i++)
{
if(map.count(ransomNote[i])>0&&map[ransomNote[i]])
{
map[ransomNote[i]]--;
}
else
{
return false;
}
}
return true;
}
优化一:
// 时间复杂度: O(n)
// 空间复杂度:O(1)
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
int record[26] = {0};
for (int i = 0; i < magazine.length(); i++) {
// 通过recode数据记录 magazine里各个字符出现次数
record[magazine[i]-'a'] ++;
}
for (int j = 0; j < ransomNote.length(); j++) {
// 遍历ransomNote,在record里对应的字符个数做--操作
record[ransomNote[j]-'a']--;
// 如果小于零说明 magazine里出现的字符,ransomNote没有
if(record[ransomNote[j]-'a'] < 0) {
return false;
}
}
return true;
}
};
优化二:
bool canConstruct(string ransomNote, string magazine) {
int hash[26] = {0};
for (char c : magazine) hash[c - 'a'] += 1;
for (char c : ransomNote)
if ((hash[c - 'a'] -= 1) < 0) return false;
return true;
}
标题思路二;暴力枚举法
分析:
但是这里需要注意两点:
- 第一点“为了不暴露赎金信字迹,要从杂志上搜索各个需要的字母,组成单词来表达意思” 这里说明杂志里面的字母不可重复使用。
- 第二点 “你可以假设两个字符串均只含有小写字母。” 说明只有小写字母,这一点很重要.
- 因为magazine的字符不能重复利用,所以不能利用
ransom的字符在magazine里面出现过这种思路(因为这样排除不掉ransom有几个相同字符,而magazine里面只有一个和其相匹配的字符例如:random(“aaas”)magainze(“aas”)这种情况),所以采用magazine里面的字符在random里面出现过吗,如果出现过就将random里面的字符删掉,直到magazine里面的字符遍历结束;如果为空,就返回真,否则返回假
bool canConstruct(string ransomNote, string magazine)
{
for (int i = 0; i < magazine.size(); i++)
{
for (int j = 0; j < ransomNote.size(); j++)
{
if (magazine[i] == ransomNote[j])
{
ransomNote.erase(ransomNote.begin() + j);
break;
}
}
}
if (ransomNote.size() == 0)
return true;
else
return false;
}