【力扣-哈希表】6、赎金信(383)

266 阅读2分钟

「这是我参与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;
    }
};

image.png

使用数组

使用数组记录下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;
    }
};

image.png