算法训练营DAY6_有效的字母异位词、两个数组的交集、快乐数、两数之和

LeetCode | 242.有效的字母异位词

题目

给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。

注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。

242.有效的字母异位词icon-default.png?t=MBR7https://leetcode.cn/problems/valid-anagram/

思考

  • 之前对哈希表不够了解,所以花了点时间去了解哈希表;
  • 自己思考的时候是想要将两个字符串的字符都取出来,然后进行比较,后面发现不可信;
  • 看了视频讲解后觉得很妙,细节看题解的备注;

题解

var isAnagram = function(s, t) {
    // 判断两个字符串的长度是否相同
    if(s.length !== t.length) return false
    // 创建一个长度为26的数组,代表着26个字母在字符串中出现的个数
    const resArray = new Array(26).fill(0)
    // 遍历取出数组中的每个数,与字母的第一位a相减
    const base = "a".charCodeAt()
    for(let i of s){
        let j = i.charCodeAt() - base
        // 数组相应位置的数加1
        resArray[j]++ 
    }
    // 另一个字符串同理
    for(let i of t){
        let j = i.charCodeAt() - base
        // 数组的相应位置减1
        resArray[j]--
    }
    // 遍历resArray数组,如果里面的元素都为0,那么就可以说明……
    for(let i = 0; i < resArray.length; i++){
        if(resArray[i] !== 0){
            return false
        }
    }
    return true
};

LeetCode | 349.两个数组的交集

题目:给定两个数组nums1nums2,返回它们的交集。输出结果中的每个元素一定是唯一的。我们可以不考虑输出结果的顺序 。

349.两个数组的交集icon-default.png?t=MBR7https://leetcode.cn/problems/intersection-of-two-arrays/

思考

  • 看了一点提示,知道这道题需要用set(因为之前的题目是没有规定数组长度的大小的,但是后面规定了数组的长小于等于1000,所以是可以用数组直接解,并且用数组反而会更快);

题解

var intersection = function (nums1, nums2) {
    // 先将两个数组转化为set去重
    nums1 = new Set(nums1)
    nums2 = new Set(nums2)
    // 创建一个新的Set
    let nums3 = new Set()
    // 迭代
    for (const item of nums1) {
        if (nums2.has(item)) {
            nums3.add(item)
        }
    }
    // 返回3
    return Array.from(nums3)
};


-----------------------------------下面是参考答案-----------------------------------------

var intersection = function(nums1, nums2) {
    // 根据数组大小交换操作的数组(我的题解因为偷懒没有判断哪个数组更大,所以如果操作到更长的数组的话,会迭代很久,是一个bug,需要注意!!!!不过这里因为规定了数组的上限,所以看似没有问题了。)
    if(nums1.length < nums2.length) {
        const _ = nums1;
        nums1 = nums2;
        nums2 = _;
    }
    const nums1Set = new Set(nums1);
    const resSet = new Set();
    // for(const n of nums2) {
    //     nums1Set.has(n) && resSet.add(n);
    // }
    // 循环 比 迭代器快
    for(let i = nums2.length - 1; i >= 0; i--) {
        nums1Set.has(nums2[i]) && resSet.add(nums2[i]);
    }
    return Array.from(resSet);
};

LeetCode | 202.快乐数

题目

编写一个算法来判断一个数 n 是不是快乐数。

「快乐数」 定义为:

对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
如果这个过程 结果为 1,那么这个数就是快乐数。
如果 n 是 快乐数 就返回 true ;不是,则返回 false 。

202.快乐数icon-default.png?t=MBR7https://leetcode.cn/problems/happy-number/

思考

  • 看了一点提示后自己写出来的,是一道信心题,就像提示说的那样,只要知道怎么将数字取平方并相加,其他的就很简单了;
  • 将数字取平方并相加后,发现题目说的很明显,只有两种结果:sum无限循环或者是等于1,所以要判断一个元素是否出现集合里的时候,就要考虑哈希法,而set里面是不会有重复元素的,所以用set

题解

var isHappy = function (n) {
    // 思路:先将n的每个位上的数字进行平方相加操作→将得到的sum添加进一个set中→一直这样做直到sum=1或者set中出现了重复的数
    let sum = 0;
    let num = n + '';
    let reSet = new Set();
    while (sum !== 1) {
        sum = 0;
        for (let i = 0; i < num.length; i++) {
            sum += num[i] * num[i]
        }
        if (!reSet.has(sum)) {
            reSet.add(sum)
            num = sum + ''
        } else {
            return false
        }
    }
    return true
};

LeetCode | 1.两数之和

题目

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出和为目标值target的那两个整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

1.两数之和icon-default.png?t=MBR7https://leetcode.cn/problems/two-sum/

思考

  • 提示说需要使用map,不过我掌握的不够熟悉,虽然用了map,但是暴力解法(hhhhh),第一次看到执行用时288ms的;
  • 看了题解过后觉得思想很妙,双层for循环是为了取出来相加,但是知道和、一个加数,另一个加数是可以通过减法减出来的!!好思想!
  • 并且题解都没有new Map(),直接是创建的一个空对象,只能说理解map理解得很深刻,不像我只会用这些方法……

题解

var twoSum = function (nums, target) {
    // 创建一个map
    var newMap = new Map()
    // 遍历数组
    for(var i = 0; i < nums.length; i++){
        // 判断newMap中是否有与nums[i]相加为target的key
        if(newMap.get(target - nums[i]) !== undefined){
            return [i, newMap.get(target - nums[i])]
        }
        // 不符合的话,就将其加入newMap
        newMap.set(nums[i], i)
    }
    return[]
};

-----------------------------------下面是参考答案-----------------------------------------

var twoSum = function (nums, target) {
  let hash = {};
  for (let i = 0; i < nums.length; i++) {  // 遍历当前元素,并在map中寻找是否有匹配的key
    if (hash[target - nums[i]] !== undefined) {
      return [i, hash[target - nums[i]]];
    }
    hash[nums[i]] = i;   // 如果没找到匹配对,就把访问过的元素和下标加入到map中
  }
  return [];
};

哈希表思路总结

  • 当我们需要查询一个元素是否出现过,或者一个元素是否在集合里的时候,就要第一时间想到哈希法;
  • 根据需要处理的数据,选择合适的结构:数组、map、set;
    • 数组的大小受限制,而且如果元素很少,而哈希值太大会造成内存空间的浪费(如果题目没有限制数组的大小,那么考虑用其他的来完成哈希表的题目);
    • set是一个集合,里面放的元素只能是一个key,set中元素不能重复(set把数值映射到key上都要做hash计算,所以set不仅占用空间比数组大,而且速度要比数组慢);
    • map是一种key value的存储结构,可以用key保存数值,用value在保存数值所在的下标;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值