代码随想录day6| 哈希表 242.有效的字母异位词 ,349. 两个数组的交集 ,202. 快乐数, 1. 两数之和

49 阅读3分钟

哈希表

  • 定义:根据关键码的形式而直接进行访问的数据结构
  • 应用:javascript 中的Object、Set、WeakSet、Map、WeakMap 都是哈希结构。
  • 用途:快速判断一个元素是否出现在集合里。

Set、WeakSet

Set类似于数组,但是元素的值都是唯一的,没有重复的值
WeakSet 结构与 Set 类似,也是不重复的值的集合。但是,它与 Set 有两个区别。

  1. WeakSet 的成员只能是对象,而不能是其他类型的值。
  2. WeakSet 中的对象都是弱引用,ES6 规定 WeakSet 不可遍历

Map、 WeakMap

  • Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。如果你需要“键值对”的数据结构,Map 比 Object 更合适。

  • WeakMapMap的区别有两点。 首先,WeakMap只接受对象(null除外)和 Symbol 值作为键名,不接受其他类型的值作为键名。

其次,WeakMap的键名所指向的对象,不计入垃圾回收机制。

习题

242.有效的字母异位词

image.png

思路: 字母为key, 出现的次数为value,判断后比较

/**
 * @param {string} s
 * @param {string} t
 * @return {boolean}
 */
var isAnagram = function(s, t) {
    if(s.length !== t.length) return false
    let hash1 = {}
    let hash2 = {}
    for(let i = 0;i<s.length;i++){
        hash1[s[i]]  = hash1[s[i]] === undefined ? 0: ++hash1[s[i]]
        hash2[t[i]]  = hash2[t[i]]=== undefined ? 0: ++hash2[t[i]]
         
    }
    let same = true
    for(let i in hash1){
        if(hash1[i] !=hash2[i]){
            same = false
            break
        }
    }
    return same

};

349. 两个数组的交集

image.png

思路:使用Set数据结构不包含重复值的特点可以很简单做出来

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number[]}
 */
var intersection = function(nums1, nums2) {
    return Array.from(new Set(nums1.filter(item=>nums2.includes(item))))
};

202. 快乐数

image.png

重点在于理解题干中说到的无限循环,即每个数的平方和会出现相同的数,然后无限循环下去

思路: 存储每次的平方和,当平方和出现过或者等于1时,不再继续计算

/**
 * @param {number} n
 * @return {boolean}
 */
     const getSquareSum = (num)=>{
        const arr = String(num).split('')
        let sum = 0
        arr.forEach(item=>{
            sum += Number(item)* Number(item)
        })
        return sum
    }

var isHappy = function(n) {
    const sumArr = []
    let squareSum = n
    let result = Boolean(squareSum === 1)
    while(squareSum != 1){
        squareSum = getSquareSum(squareSum)
        if(squareSum === 1){
            result = true
        }
        if(sumArr.indexOf(squareSum) > -1){
            return false
        }else{
             sumArr.push(squareSum)
        }
    }
    return result
};

疑惑: Set.has 和 数组 indexOf哪种更高效呢

1. 两数之和

image.png

思路: 判断一个元素是否出现过!

[2,7,11,15] target = 9,遍历2的时候查看9-2 = 7,7是否出现过,遍历7的时候查看2是否出现过

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function (nums, target) {
    const map = new Map()
    let res = []
    for (let i = 0; i < nums.length; i++) {
        const diff = target - nums[i]
        if (map.has(diff)) {
            res = [map.get(diff), i]
            return res;
        } else {
            map.set(nums[i], i)
        }
    }

    return res
};
    

附: forEach 中不能使用break,使用return只是跳出本次循环,后面的循环还会执行,所以这里使用for

总结

哈希表消耗了内存空间,减少了运行时间,这就是「空间换时间」。
很多涉及到「两个变量」的题目,都可以枚举其中一个变量,把它当成常量看待,从而转换成「一个变量」的问题。

代码实现时,通常来说枚举右,寻找左 是更加好写的。