383. 赎金信
- 给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。
- 如果可以,返回 true ;否则返回 false 。
- magazine 中的每个字符只能在 ransomNote 中使用一次。
一、原来的想法
-
把magazine字符串中的分割成字符数组,存到哈希表中。
-
然后遍历ransomNote中的每个字符,检查哈希表中是否存在。存在就把它删除(防止有多个相同的数字),如果不存在就false.
-
问题在于:magazine存在相同的值,但是magazine中的每个字符只能在ransomNote中使用一次。所以不能用set. -
如果用map,那么存哈希表的时候,如果是值作为key,由于key的唯一性,会去掉重复的元素。 如果是值作为value,那么在检查哈希表中是否有值的时候,还要靠考虑这个值的索引,才能通过get()方法得到对应的值,而索引是未知的。 -
所以最后使用数组实现了,但是有点慢。
var canConstruct = function(ransomNote, magazine) {
// 1、将ransomNote存到哈希表中
let help = []
// 转换字符数组形式
let m = magazine.split('')
for(let i=0; i<m.length; i++){
help.push(m[i])
}
// 2、检查magazine里的每个字符在哈希表中是否存在
for(let s of ransomNote.split('')){
if(help.indexOf(s) != -1){
// 存在,就把这个元素从哈希表中剔除
help.splice(help.indexOf(s),1)
}else{
return false
}
}
return true
};
二、官方题解
题目思想和[有效的字母异位词](https://juejin.cn/post/7138698862029930532)类似,因为都是针对26个字母,所以可以维护一个26字母长的数组,把索引当作元素的值,值当作元素的数量
var canConstruct = function(ransomNote, magazine) {
// 比较长度
if(magazine.length < ransomNote.length) return false
// 将magazine里的字母和数量进行存储
const cnt = new Array(26).fill(0)
for(const m of magazine){
// 由于组成的都是小写字母,所以每个字母对应一个索引下标,值就是数量
cnt[m.charCodeAt() - 'a'.charCodeAt()]++
}
// 遍历ransomNote里的值,将哈希表中的数量--
for(const r of ransomNote){
cnt[r.charCodeAt() - 'a'.charCodeAt()]--
// 如果减去之后小于0,证明哈希表中没有这个字母
if(cnt[r.charCodeAt() - 'a'.charCodeAt()] < 0){
return false
}
}
return true
};