给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。
如果可以,返回 true ;否则返回 false 。
magazine 中的每个字符只能在 ransomNote 中使用一次。
示例:
输入:ransomNote = "a", magazine = "b"
输出:false
示例 2:
输入:ransomNote = "aa", magazine = "ab"
输出:false
示例 3:
输入:ransomNote = "aa", magazine = "aab"
输出:true
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/ransom-note
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
第一次遇到这种解决方式(个人理解,若有错误,欢迎指正,谢谢!!)
/**
* @param {string} ransomNote
* @param {string} magazine
* @return {boolean}
*/
var canConstruct = function(ransomNote, magazine) {
//哈希解法
//用一个长度为26的数组还记录magazine里字母出现的次数。
//然后再用ransomNote去验证这个数组是否包含了ransomNote所需要的所有字母。
const strArr = new Array(26).fill(0),
base = "a".charCodeAt();//返回字符串第一个字符的 Unicode 编码(H 的 Unicode 值)
for(const s of magazine) {
strArr[s.charCodeAt() - base]++;
//记录magazine里的元素出现的次数。strArr是26个字母,起始的次数全是零
//假如出现一次b,那么就在b的编码减去a的编码的数字为下标的地方加一,表示b出现过一次
//同理,其他元素出现也是在该元素的编码减去a的编码的数字为下标来计数
//s则是用来遍历magazine里的每个字母
}
for(const s of ransomNote) {
const index = s.charCodeAt() - base;
//index是用来寻找ransomNote中当前字母在strArr中对应的下标
if(!strArr[index]) return false;
//如果,当前字母的次数不存在了,那么久说明ransomNote里的元素不能组成magazine
strArr[index]--;
//否则就将次数减一
}
return true;
};
其中关键的思路就是将字母转换为在26个字母相对应的位置进行计数。
记录a的编码,然后再其他字母转化为编码时,减去a的编码,就可以在以当前数字为下标的数组中记录一次出现的次数。当这个字符串遍历结束且计数结束,就可以去遍历下一个字符串。将当前字符串的次数用上一个字符串的次数减一来计算,这样加入当前字符串的某个元素在上次字符串的计数中次数为零,就证明上一个字符串无法组成当前的字符串。