「这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战」
383. 赎金信
题目描述
给定一个赎金信 (ransom
) 字符串和一个杂志(magazine
)字符串,判断第一个字符串 ransom
能不能由第二个字符串 magazines
里面的字符构成。如果可以构成,返回 true
;否则返回 false
。
(题目说明:为了不暴露赎金信字迹,要从杂志上搜索各个需要的字母,组成单词来表达意思。杂志字符串中的每个字符只能在赎金信字符串中使用一次。)
示例 1:
输入: ransomNote = "a", magazine = "b"
输出: false
示例 2:
输入: ransomNote = "aa", magazine = "ab"
输出: false
示例 3:
输入: ransomNote = "aa", magazine = "aab"
输出: true
思路
判断字符串
A
是否可由字符串B
中的字符组成,所以就要统计两个字符串中的相同的字符个数是否相同,所以可以考虑使用map
, 这里不考虑字符的顺序,所以可以使用unordered_map
。再考虑存储A字符串或是B字符串中的字符。因为是判断B是否包含A所需要的所有字符,所以使用unordered_map
来存储字符串B中的字符 。 算法步骤
- 定义
unordered_map
- 遍历字符串
B
中的字符,存储到map
中 - 再遍历字符串
A
中的字符,如果不在map
中,就直接返回false
- 如果在
map
中,将其对应的值减1 - 遍历完字符串
A
后,判断map
中的值是否有小于0的,如果有,就表示不能满足条件,返回false
- 如果没有小于0的值,则满足条件,返回
true
使用map
class Solution
{
public:
bool canConstruct(string ransomNote, string magazine)
{
unordered_map<char, int> umap;
// 将 magazine 中的字符全部添加到umap中
for (char c : magazine)
{
umap[c] += 1;
}
// 查询ransomNote中的字符是否在umap中,
// 如果在umap中查到对应的字符,就将其值减1
// 如果不在,就不满足条件,返回false
for (char c : ransomNote)
{
auto pos = umap.find(c);
if (pos != umap.end())
{
umap[c]--;
}
else
{
return false;
}
}
// 遍历完 ransomNode ,判断umap中的key对应的value是否存在小于0的值
bool flag = true;
for (pair<char, int> m : umap)
{
// 如果存在小于0的值,就表示不满足条件,返回false
if (m.second < 0)
{
flag = false;
}
}
return flag;
}
};
使用数组
使用数组记录下26个字母出现的次数(思路与unordered_map的相似)
class Solution1
{
public:
bool canConstruct(string ransomNote, string magazine)
{
// 这里只考虑只有小写字母时的情况(题述提示)
// 初始化 26个字符的空间,记录每个字符出现的次数
int record[26] = {0};
// 首先遍历 magazine,记录其中字出现的次数
for (char c : magazine)
{
record[c - 'a'] += 1;
}
// 遍历 ransomNote,将其字符对应的次数减1
for (char c : ransomNote)
{
record[c - 'a'] -= 1;
}
// 遍历record数组,如果存在小于0的数值,就表示不满足条件
for (int v : record)
{
if (v < 0)
{
return false;
}
}
return true;
}
};