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

2024-08-05 16:52:13 浏览数 (1)

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

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

一、哈希表的定义

哈希表(Hash Table),又称为散列表,是一种通过哈希函数组织数据,以支持快速插入和搜索的数据结构。哈希表的核心思想是通过一个哈希函数将输入的键值(Key)映射到一个地址,然后通过这个地址来访问存储的数据值(Value)。

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:

代码语言:javascript复制
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:使用遍历

代码语言:javascript复制
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向下取整。

代码语言:javascript复制
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的下标。

代码语言:javascript复制
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 就可以了。

代码语言:javascript复制
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;
};

最后

0 人点赞