【代码随想录算法训练营】D6 242.有效字母的异同 349. 两个数组的交集 202. 快乐数 1. 两数之和

本文探讨了哈希表在解决编程问题中的重要作用,如在有效字母异同、数组交集、快乐数和两数之和等题目中的应用。通过使用哈希表,可以快速判断元素出现、去重、检测循环以及高效查找。同时,文章还分享了一些代码实现上的优化技巧,如利用Set去重和提前跳出循环等。
摘要由CSDN通过智能技术生成

今日题目:

  • 242.有效字母的异同
  • 349. 两个数组的交集
  • 202. 快乐数
  • 1. 两数之和

解题思想:

常用的三种哈希结构:数组、set、map,当我们遇到了要快速判断一个元素是否出现在集合里的时候,就可以考虑哈希法,它使用空间换取时间。

  1. 利用小写字母的ASCIⅡ码连续

可以不用关心具体ASCIⅡ码是多少,但是我们知道的是它们一定是连续的,利用charCodeAt()方法求得具体ASCIⅡ码。所以可以定义一个长为26的数组,用来统计各个字符出现的频率。也可以使用map作哈希表来统计。

  1. 数组去重

在349题,两个数组的交集中,很重要的一点是答案需要去重处理,所以马上想到利用Set特性进行数组去重。将一个表设置为哈希表,遍历另一个表,判断每个元素是否在哈希表中出现,如果出现了,那么就把它加入到答案数组中。

  1. 无限循环

202题快乐数,此题的关键就是如何出现破除无限循环并跳出。在求和的过程中,只要重复出现过之前出现过的数,我们就可以知道它必定是无限循环。所以利用哈希表来记录每个sum,当sum再次出现就可以直接return false。否则一直找到1为止。

  1. 合理利用map的key和value

第一题,两数之和,梦开始的地方,写过好多遍熟悉到已经不用动脑子就可以写出来了哈哈。我们用Map来存储出现过的数字时,存储结构是{key:数据元素, value:数组元素对应下标},因为只有这样存储,我们才可以通过map.has()快速判断某个数是否已经出现在了map中,( map.has()方法是用来判断键是否存在,而不是值是否存在)。因为返回的是数组下标,我们再利用map.get()获取对应数据所在的下标。


代码:

  • 242.有效字母的异同
//数组实现版
var isAnagram = function(s, t) {
    if(s.length !== t.length) return false
    const res = new Array(26).fill(0)
    const base = "a".charCodeAt()

    for(const i of s){
        res[i.charCodeAt()-base]++
    }

    for(const i of t){
        if(!res[i.charCodeAt() - base]) return false
        res[i.charCodeAt()-base]--
    }
    return true
};

//map实现版
var isAnagram = function(s, t) {
    if(s.length !== t.length) return false
    const map = new Map()
    for(let i = 0; i<s.length; i++) {
        遍历字符串s,对s操作
        if(map.has(s[i])){
            map.set(s[i],map.get(s[i])+1)
        } else {
            map.set(s[i], 1)
        }
        //遍历字符串t,对t操作
        if(map.has(t[i])){
            map.set(t[i],map.get(t[i])-1)
        } else {
            map.set(t[i], -1)
        }
    }
    for(const item of map){
        if(item[1] !== 0) return false
    }
    return true
};
  • 349 . 两个数组的交集
var intersection = function(nums1, nums2) {
    //nums1为长度更长的数组
    if(nums1.length < nums2.length) {
        const temp = nums1
        nums1 = nums2
        nums2 = temp
    }

    const set = new Set(nums1) //利用set特性给nums1去重
    const res = new Set() //保存答案的set集合, 给答案集合自动去重
    for(const num of nums2) {
        set.has(num) && res.add(num)
    }

    return Array.from(res)
};
  • 202 . 快乐数
var isHappy = function(n) {
    const set = new Set()

    //如果在循环中某个值重复出现,说明陷入了死循环,不会进入此循环,直接通过下面判断返回true
    //只有在set中没有的时候,才需要进入此循环
    while(n !== 1 && !set.has(n)) {
        set.add(n)
        n= getSum(n)
    }

    return n==1
};
//专门用来计算每位数的和
var getSum = function(n) {
    let sum = 0
    while(n) {
        sum += (n%10) **2
        n = Math.floor(n/10)
    }
    return sum
}
    1. 两数之和
var twoSum = function(nums, target) {
    const map = new Map()
    for(let i = 0; i<nums.length; i++) {
        if(map.has(target-nums[i])){
            return [map.get(target-nums[i]), i]
        } else {
            map.set(nums[i], i)
        }
    }
    return []
};

总结:

不得不说代码随想录给出的题解比我自己的优美太多了…快乐数这道题虽然不难,但是在细节实现上有很多我想不到的优雅的写法:比如,循环计算的这部分代码,当此时的sum已经存在于set中时,可以无需进入while代码块,直接在最后使用n==1来控制返回true还是false,while循环中只需要执行n不等于1且set中没有出现过n的逻辑。以及getSum函数,我自己一开始实现是先把它转为数组,再遍历相加,多走了一步弯路。

    while(n !== 1 && !set.has(n)) {
        set.add(n)
        n= getSum(n)
    }
    return n==1
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值