算法合集 | 哈希表 | Leetcode 349,202,1

86 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第11天,点击查看活动详情

前言

本系列文章主要会总结一些常见的算法题目以及算法的易错点,难点,以及一些万用的公式,并且结合实际的 Leetcode 题目来进行加深理解以及实际应用,算法这种东西,属于是一到用时方恨少的类型,在平时总结一些常见的简单算法,经常磨练自己的算法思维,对于日常的开发还是能有不少的帮助的。

  • 今天主要实践刷一下一些简单的哈希表题目。

349. 两个数组的交集

题目

给定两个数组,编写一个函数来计算它们的交集。

说明:  输出结果中的每个元素一定是唯一的。 我们可以不考虑输出结果的顺序。

暴力解题

首先,暴力解法是有的,循环第一个字符串拿着每一个字符去循环第二个字符串作对比,这样时间复杂度来到了 O(n2) 性能就一定是没那么美丽了。

function intersection(nums1: number[], nums2: number[]): number[] {
    const res = []
    nums1.forEach(item1=>{
        nums2.forEach(item2=>{
            if(item1==item2 && !res.includes(item1)) res.push(item1)
        })
    })
    return res
};

图片.png

哈希优化

那接下来用哈希表来优化一下。

哈希表的思路是先用一个set表保存下第一个字符串为set1,然后循环第二个字符串去判断set1是否存在这个数字,存在的话就保存为一个结果set表为resSet,因为是用set保存结果,所以结果中重复的数也会被过滤,最后用 Array.from 就可以把 set 表转为数组。

function intersection(nums1: number[], nums2: number[]): number[] {
    let resSetSet<number> = new Set();
    let nums1SetSet<number> = new Set(nums1);
    for (let num of nums2) {
        if (nums1Set.has(num)) {
            resSet.add(num);
        }
    }
    return Array.from(resSet);
};

图片.png

202. 快乐数

题目

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

「快乐数」定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。如果 可以变为  1,那么这个数就是快乐数。

如果 n 是快乐数就返回 True ;不是,则返回 False 。

解题

题目中说了会 无限循环,那么也就是说求和的过程中,sum会重复出现!,比如题目中给出的例子

图片.png

n = 2 的这种时候哦就是,所以我们需要保存下每一次计算的结果,来判断这个过程是否发生了重复,这个时候,就需要用一个集合来保存下之前的所有结果,并且判断新的结果是否重复。

当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法了。

所以这道题目使用哈希法,来判断这个sum是否重复出现,如果重复了就是return false, 否则一直找到sum为1为止

function isHappy(n: number): boolean {
    let setSet<number> = new Set();
    while (n !== 1 && !set.has(n)) {
        set.add(n);
        n =  String(n).split("").reduce((pre, cur) => (pre + Number(cur) * Number(cur)), 0);
    }
    return n === 1;
};

图片.png

1. 两数之和

题目

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

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。

解题

还是根据在一个集合中快速去查找某个数的思路,我们把数组nums的每一个数存进一个map表,在保存的过程当中,去判断当前的数,和map表中的数,相加是否会等于target,也就是map表当中是否存在 target - 当前数,找到就返回下标,没有就返回空数组

  • 利用数组作为map表
function twoSum(nums: number[], target: number): number[] {
    let map = []
    for(let [index, item] of nums.entries()) {
       if(map.includes(target-item)) return [map.indexOf(target-item), index]
        else {
            map[index] = item
        } 
    }
    return []
};

图片.png