哈希表6:赎金信(383)
本题如下:(链接:https://leetcode.cn/problems/ransom-note/)
题目:给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。
如果可以,返回 true ;否则返回 false 。
magazine 中的每个字符只能在 ransomNote 中使用一次。

思路:
这道题目和题库第242题有效的字母异位词很像,但有效的字母异位词这题相当于求字符串a 和 字符串b 是否可以相互组成 ,而这道题目是求字符串a能否组成字符串b,而不用管字符串b能不能组成字符串a。
本题判断第一个字符串ransom能不能由第二个字符串magazines里面的字符构成,但是这里需要注意两点。
(1)第一点“为了不暴露赎金信字迹,要从杂志上搜索各个需要的字母,组成单词来表达意思” 这里说明杂志里面的字母不可重复使用。
(2)第二点 “你可以假设两个字符串均只含有小写字母。” 说明只有小写字母,这一点很重要。
解法:
(1)对于本题的第一个思路其实就是暴力枚举了,两层for循环,不断去寻找,代码如下:
1 // 时间复杂度: O(n^2) 2 // 空间复杂度:O(1) 3 class Solution { 4 public: 5 bool canConstruct(string ransomNote, string magazine) { 6 for (int i = 0; i < magazine.length(); i++) { 7 for (int j = 0; j < ransomNote.length(); j++) { 8 // 在ransomNote中找到和magazine相同的字符 9 if (magazine[i] == ransomNote[j]) { 10 ransomNote.erase(ransomNote.begin() + j); // ransomNote删除这个字符 11 break; 12 } 13 } 14 } 15 // 如果ransomNote为空,则说明magazine的字符可以组成ransomNote 16 if (ransomNote.length() == 0) { 17 return true; 18 } 19 return false; 20 } 21 };
这种方法的时间复杂度是比较高的,而且里面还有一个字符串删除也就是erase的操作,也是费时的,当然这段代码也可以解决这道题。
(2)哈希法
因为这道题目只有小写字母,那么就可以采用空间换取时间的哈希策略, 用一个长度为26的数组去记录magazine里字母出现的次数。
然后再用ransomNote去验证这个数组是否包含了ransomNote所需要的所有字母。
因此这道题依然是数组在哈希法中的应用。
但其实在本题的情况下,如果使用map的空间消耗要比数组大一些的,因为map要维护红黑树或者哈希表,而且还要做哈希函数,是费时的,数据量大的话就能体现出来差别了。 所以本题使用数组更加简单直接有效!
C++代码如下:
1 // 时间复杂度: O(n) 2 // 空间复杂度:O(1) 3 class Solution { 4 public: 5 bool canConstruct(string ransomNote, string magazine) { 6 int record[26] = {0}; 7 //add 8 if (ransomNote.size() > magazine.size()) { 9 return false; 10 } 11 for (int i = 0; i < magazine.length(); i++) { 12 // 通过recode数据记录 magazine里各个字符出现次数 13 record[magazine[i]-'a'] ++; 14 } 15 for (int j = 0; j < ransomNote.length(); j++) { 16 // 遍历ransomNote,在record里对应的字符个数做--操作 17 record[ransomNote[j]-'a']--; 18 // 如果小于零说明ransomNote里出现的字符,magazine没有 19 if(record[ransomNote[j]-'a'] < 0) { 20 return false; 21 } 22 } 23 return true; 24 } 25 };
接下来给出相应的Java版本:
1 class Solution { 2 public boolean canConstruct(String ransomNote, String magazine) { 3 // 定义一个哈希映射数组 4 int[] record = new int[26]; 5 6 // 遍历 7 for(char c : magazine.toCharArray()){ 8 record[c - 'a'] += 1; 9 } 10 11 for(char c : ransomNote.toCharArray()){ 12 record[c - 'a'] -= 1; 13 } 14 15 // 如果数组中存在负数,说明ransomNote字符串总存在magazine中没有的字符 16 for(int i : record){ 17 if(i < 0){ 18 return false; 19 } 20 } 21 22 return true; 23 } 24 }
本文来自博客园,作者:Ricentch,转载请注明原文链接:https://www.cnblogs.com/cnwsh/p/16684434.html

浙公网安备 33010602011771号