Bootstrap

TypeScript算法题实战——哈希表篇(Set和Map的基本用法、快乐数、两数相加、四数相加)

哈希表可以用来快速判断一个元素是否出现集合里。常见的哈希表有三种形式:数组、set (集合)、map(映射)

本系列博文将通过一些力扣算法题目,边学习TypeScipt边实战算法,这篇将通过一些经典算法题熟悉TS语言哈希表的一些基本操作。(部分算法思想参考于程序员Carl:代码随想录

一、哈希表的定义

1.1、集合set

定义:let storeSet: Set<number> = new Set();
判断是否包含:if(storeSet.has(n))
往集合中增加元素:storeSet.add(n)
删除某个元素:storeSet.delete(n)
清空set:storeSet.clear()
获取set的所有值:let values = set.values();
遍历set:

let values = set.values();
for (let value of values) {
  console.log(value);
}

1.2、映射Map

定义:let myMap: Map<number, string> = new Map(); // key value结构
得到map的大小: myMap.size
增加map的元素:myMap.set(1, "和键1关联的值");
是否包含某个成员:myMap.has(key)
删除成员:myMap.delete(key)
获取map的所有value值:myMap.values()
获取map的所有key值:myMap.keys()
根据key,得出value:myMap.get(1)
根据value,得出key:使用遍历

let myMap: Map<number, string> = new Map();
    myMap.set(1, "和键1关联的值");
    myMap.set(2, "和键2关联的值");
    myMap.set(3, "和键3关联的值");
    console.log(myMap.values());
    console.log(myMap.keys());
    console.log(myMap.get(1));

二、快乐数

力扣链接:https://leetcode.cn/problems/happy-number/

2.1、题目描述

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

2.2、示例

在这里插入图片描述

2.3、题解

题目中说了会 无限循环,那么也就是说求和的过程中,sum会重复出现,于是我们就可以用上哈希表来判断这个sum是否重复出现,如果重复了就是return false, 否则一直找到sum为1为止。

要注意的是,ts的number类型是浮点数,做除10时要使用floor向下取整。

function isHappy(n: number): boolean {
    
    let storeSet: Set<number> = new Set();
    while(!storeSet.has(n) && n != 1){
       storeSet.add(n);
       let tmp: number = 0;
       let numn: number = n;
       while(numn != 0){
           tmp = tmp + (numn % 10) * (numn % 10);
           numn = Math.floor(numn / 10);
       }
       n = tmp;
    }
    if(n == 1)
        return true;
    else 
        return false;
};

三、两数之和

力扣链接:https://leetcode.cn/problems/two-sum/

3.1、题目描述

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

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

3.2、示例

在这里插入图片描述

3.3、题解

用哈希map来存数字,map目的用来存放我们访问过的元素,因为遍历数组的时候,需要记录我们之前遍历过哪些元素和对应的下表,这样才能找到与当前元素相匹配的(也就是相加等于target)
比如2 3 5 6 9 8 target=7
遍历数组,存入2,存入3之前找一下是否有4,没有,然后存入5,存入5之前找一下是否有2,发现哈希map里有,则输出当前下标和value2的下标。

function twoSum(nums: number[], target: number): number[] {
    let resMap: Map<number, number> = new Map();
    let index: number = 0;
    for(let i: number = 0; i < nums.length; i++){
        let anoNum: number | undefined =  resMap.get(target - nums[i]);
        if(anoNum !== undefined){
            return [i , anoNum];
        }
        resMap.set(nums[i], i); //key value结构来存放,key来存元素,value来存下标
    }
    return nums;
};

四、四数相加||

力扣链接:https://leetcode.cn/problems/4sum-ii/submissions/

4.1、题目描述

给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:

0 <= i, j, k, l < n
nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0

4.2、示例

在这里插入图片描述

4.3、题解

因为题目只要求得到有多少组,并不要求输出每一组的详细情况,且不用考虑重复的情况,我们将其分成两组,算和就行了。
也就是先算A和B数组的和有多少种情况,且每种和出现了几次,然后再算C和D中的数组的和满足条件的情况,找到如果 0-(c+d) 在map中出现过的话,就用count把map中key对应的value也就是出现次数统计出来。最后返回统计值 count 就可以了。

function fourSumCount(nums1: number[], nums2: number[], nums3: number[], nums4: number[]): number {
    let myMap: Map<number, number> = new Map(); 
    for(let i of nums1){
        for(let j of nums2){
            let sumTemp: number | undefined = myMap.get(i + j);
            myMap.set(i + j,sumTemp? sumTemp + 1 : 1);
        }
    }
    let res: number = 0;
    for(let i of nums3){
        for(let j of nums4){
            let sumTemp: number | undefined = myMap.get(0 - i - j)
            if(sumTemp)
                res = res + myMap.get(0 - i - j);
        }
    }
    return res;
};

最后

💖 个人简介:人工智能领域研究生,目前主攻文本生成图像(text to image)方向

📝 关注我:中杯可乐多加冰

🔥 限时免费订阅:TypeScript实战

🎉 支持我:点赞👍+收藏⭐️+留言📝

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;