这是 leetcode 面试刷题一题多解系列的第16篇,给定一个赎金信 (ransom) 字符串和一个杂志(magazine)字符串,判断第一个字符串ransom能不能由第二个字符串magazines里面的字符构成。如果可以构成,返回 true ;否则返回 false。
题目
赎金信
来源:力扣(LeetCode)
链接:leetcode.cn/problems/ra…
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解法一:哈希表
-
遍历杂志字符串 magazine,并将其中每个字符出现的次数保存到哈希表中。
-
遍历赎金信字符串 ransomNote,在哈希表中查找对应的字符出现次数,若存在且数量大于 0,则将该字符的出现次数减 1;否则直接返回 false。
-
若能够遍历完赎金信字符串,则返回 true。
时间复杂度:O(m+n),其中 m 和 n 分别是字符串 ransomNote 和 magazine 的长度。
空间复杂度:O(n),其中 n 是字符串 magazine 的长度。哈希表存储字符串中每个字符出现的次数,最多不会超过字符串的长度。
var canConstruct = function(ransomNote, magazine) {
const hash = new Map();
for (let i = 0; i < magazine.length; i++) {
if (hash.has(magazine[i])) {
hash.set(magazine[i], hash.get(magazine[i]) + 1);
} else {
hash.set(magazine[i], 1);
}
}
for (let i = 0; i < ransomNote.length; i++) {
if (hash.has(ransomNote[i]) && hash.get(ransomNote[i]) > 0) {
hash.set(ransomNote[i], hash.get(ransomNote[i]) - 1);
} else {
return false;
}
}
return true;
};
解法二: 数组计数
- 首先创建两个长度为 26 的数组
ransomArr
和magazineArr
,分别用于记录赎金信和杂志中每个字符出现的次数。 - 遍历赎金信字符串
ransomNote
,将每个字符出现的次数存储到ransomArr
中对应位置上。 - 遍历杂志字符串
magazine
,将每个字符出现的次数存储到magazineArr
中对应位置上。 - 最后遍历长度为 26 的数组
ransomArr
,如果ransomArr[i]
的值大于magazineArr[i]
的值,说明字符i + 'a'
在杂志中的出现次数不足以满足赎金信,返回 false。 - 如果遍历完成后仍没有返回 false,则说明可以拼成赎金信,返回 true。
时间复杂度:O(m+n),其中 m 和 n 分别是字符串 ransomNote 和 magazine 的长度。
空间复杂度:O(1),因为数组的长度为 26,与输入字符串的长度无关。
function canConstruct(ransomNote, magazine) {
const ransomArr = new Array(26).fill(0);
const magazineArr = new Array(26).fill(0);
for (let i = 0; i < ransomNote.length; i++) {
ransomArr[ransomNote.charCodeAt(i) - 'a'.charCodeAt()]++;
}
for (let i = 0; i < magazine.length; i++) {
magazineArr[magazine.charCodeAt(i) - 'a'.charCodeAt()]++;
}
for (let i = 0; i < 26; i++) {
if (ransomArr[i] > magazineArr[i]) {
return false;
}
}
return true;
}
我的更多前端资讯
欢迎大家技术交流 资料分享 摸鱼 求助皆可 —链接