打卡-算法训练营-Day6 | 242.有效的字母异位词;349. 两个数组的交集;202. 快乐数 ;1. 两数之和

51 阅读3分钟

哈希法

什么情况下适合用哈希法?

给一个元素,判断这个元素是否在集合中

哈希法常用的数据结构有:数组、set、map,怎么区分使用场景?

数组:集合长度不大

set:集合需要去重

map:需要存储两个变量

有效的字母异位词

leetcode链接:leetcode.cn/problems/va…

自己AC了,但是思路比较麻烦,不推荐,学习下哈希法

这道题目使用数组数据结构,因为英文字母只有26种,可以枚举出来,长度不大

一个比较取巧的点是,要让a在数组中对应下标0,那么需要减去一个a的ASCII码

第一次遍历s字符串,将s中字母出现的次数添加到哈希表中

第二次遍历t字符串,将t中字母出现的次数从哈希表中删除

第三次遍历哈希表,如果是有效的字母异位词,那么所有元素都是0

var isAnagram = function(s, t) {
  const hashMap = new Array(26).fill(0);
  const offset = "a".charCodeAt(0);

  // 要注意,在JavaScript中两个字符串不能相减,会返回NaN
  for (let i = 0; i < s.length; i++) {
    hashMap[s.charAt(i).charCodeAt(0) - offset]++;
  }

  for (let i = 0; i < t.length; i++) {
    hashMap[t.charAt(i).charCodeAt(0) - offset]--;
  }

  for (let i = 0; i < hashMap.length; i++) {
    if (hashMap[i] !== 0) {
      return false;
    }
  }
  return true;
};

两个数组的交集

leetcode链接:leetcode.cn/problems/in…

怎么判断两个数组有交集,那肯定是数组1的某个元素出现在数组2中,那就可以使用哈希法

这道题目使用set数据结构,我使用了两个set数据结构的变量AC的,其实可以只使用一个

var intersection = function(nums1, nums2) {
  // JavaScript中set会自动去重
  let set = new Set(nums1);
  let result = new Set();

  // 查找nums[i]元素是否在set集合中
  for (let i = 0; i < nums2.length; i++) {
    if (set.has(nums2[i])) {
      result.add(nums2[i]);
    }
  }

  return Array.from(result);
};

快乐数

leetcode链接:leetcode.cn/problems/ha…

哈希表保存最新数字,不是快乐数会成环,在这个提示下AC了

题目中说了,不是快乐数无限循环,说明求和的过程中,和会重复出现(破题的关键)

var isHappy = function(n) {
  let map = {};

  while (map[n] !== 2) {
    // 把数字转为字符串方便处理
    let str = String(n);
    let newNum = 0;
    
    // 求和
    for (let i = 0; i < str.length; i++) {
      newNum += Math.pow(Number(str.charAt(i)), 2);
    }
    
    if (newNum === 1) return true;
    
    // 新数字不等于1就存储在哈希表里面
    if (map[n]) {
      map[n] += 1;
    } else {
      map[n] = 1;
    }
    
    // n变成新的数字,继续求和
    n = newNum;
  }
  
  return false;
};

学习下使用set数据结构的方法

var isHappy = function(n) {
    let set = new Set();

    while (n !== 1 && !set.has(n)) {
        // 求和
        let str = String(n);
        let newNum = 0;
        for (let i = 0; i < str.length; i++) {
            newNum += Math.pow(Number(str.charAt(i)), 2);
        }
        set.add(n);
        n = newNum;
    }

    return n === 1;
};

两数之和

leetcode链接:leetcode.cn/problems/tw…

为什么可以使用哈希法?

以 nums = [2,7,11,15], target = 9 举例

对于nums的第一个元素2,如果想要找到另外一个元素,使得两个元素相加等于target,target - 2 = 7,意味着7这个元素必须出现在nums集合中,符合使用哈希法的情况

为什么使用map数据结构?并且key是元素,value是下标

需要知道一个元素是否出现过,同时还需要知道这个元素对应的下标,那就需要存储两个变量,使用map

我们要查找的是一个元素是否出现过,那么应该把元素作为key

var twoSum = function(nums, target) {
    let hash = {};
    for (let i = 0; i < nums.length; i++) {
        if (hash[target - nums[i]] !== undefined) {
            return [i, hash[target - nums[i]]];
        } else {
            hash[nums[i]] = i;
        }
    }
    return [];
};