/** * https://leetcode.cn/problems/ransom-note/?envType=study-plan-v2&envId=top-interview-150 * @param {string} ransomNote * @param {string} magazine * @return {boolean} */ const canConstruct = function (ransomNote, magazine) { }; /* 思路:用hash表统计magazine中的字符出现的数量,之后遍历ransomNote,如果ransomNote中有字符不在这个hash表中,说明magazine不能 构成ransomNote,如果这个字符在magazine中存在,就使其计数减1,如果计数为零就从哈希表中删除这个字符 */ function f1(ransomNote, magazine) { const map = new Map(); // 利用hash计数 for (let i = 0; i < magazine.length; i++) { map.set(magazine[i], (map.get(magazine[i]) || 0) + 1); // 如果map中有这个字符就在原有的基础上加1,没有就设置成1 } // 遍历ransomNote中的字符,如果字符在map中不存在就返回false for (let i = 0; i < ransomNote.length; i++) { const char = ransomNote[i]; if (map.has(char)) { map.set(char, map.get(char) - 1); // 如果发现当前字符计数为零,从map中删除这个字符 if (map.get(char) === 0) { map.delete(char); } } else { return false; } } return true; } /* 使用数组来代替hash表,因为题目所给的测试用例只有26个小写的英文字符,可以使用一个长度为26的数组,数组的第一个位置代表a,最后一个位置代表 z,每个位置的值代表这个字符在magazine中出现的位置。 思考:为什么使用数组会更快,虽然hash查找操作时间复杂度理论上式O(1),但是hash计数,到对应的链表查找数据还是需要花费时间的,在数据量 大的时候可以认为是O(1),但是我们只需统计26个英文字符的数量,直接使用数组,数组在内存中是连续的,通过偏移量查找,非常快 */ function f2(ransomNote, magazine) { const charsCount = new Array(26).fill(0); // 统计magazine中每一个字符出现的次数 // 统计magazine中的字符 for (let i = 0; i < magazine.length; i++) { const index = magazine.charCodeAt(i) - 97; charsCount[index]++; } // 遍历ransomNote中的字符在charscount中是否存在 for (let i = 0; i < ransomNote.length; i++) { const index = ransomNote.charCodeAt(i) - 97; // if (charsCount[index] > 0) { // charsCount[index]--; // } else { // return false; // } if (charsCount[index] === 0) return false; charsCount[index]--; } return true; }