算法60天:Day 6数组的进阶:哈希表

代码随想录(截图自参考【1】)
代码随想录(截图自参考【1】)

本系列是代码随想录算法训练营的学习笔记之day6,主要记录一下刷题的过程,以及核心知识点和一些值的记录的问题。

代码随想录的资源都是免费的,具体可以看参考链接【1】。

今日知识点

哈希表理论基础:

  • 哈希表,散列表,都指的是hash table;
  • 哈希表是根据关键码的值而直接进行访问的数据结构(比如python中的字典);
  • 数组其实也是hash表,其key就是下标,value是对应的元素;
alt
  • 哈希表适合用于快速查询;
  • 哈希表是以空间换时间;

哈希函数

比如要查询一个同学在不在一个学校,我们只需要初始化把这所学校里学生的名字都存在哈希表里,在查询的时候通过索引直接就可以知道这位同学在不在这所学校里了。 将学生姓名映射到哈希表上就涉及到了hash function ,也就是哈希函数。

alt

哈希函数的具体解释可以看参考【1】和参考【2】,简单理解就是通过哈希函数,可以获取key对应的数组中的下标,通过下标直接去索引。

  • 如果两个key被映射到同一个哈希表的相同索引,就发生了哈希碰撞(解决方法见参考【1】或者自行百度。。进阶知识了。。);

今日题目

  1. 有效的字母异位词(242)

给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。

链接:https://leetcode.cn/problems/valid-anagram

解题思路

  • 根据提示,s和t只包括小写字母,所以建立一个长度26的数组,先对s进行判断,统计s中出现的各个字母频次做加法;然后对t进行判断,统计t中出现的各个字母频次,不过要做减法;
  • 然后对建立的数组绝对值求和,或者判断是否有不是0的元素,如果有,就说明不是字母异位词;
class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        records = [0]*26
        for i in s:
            index = ord(i) - ord('a')
            records[index] += 1
        for i in t:
            index = ord(i) - ord('a')
            records[index] -= 1
        s = sum([abs(i) for i in records])

        return False if s!= 0 else True
  1. 两个数组的交集(349)

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

链接:https://leetcode.cn/problems/intersection-of-two-arrays/

解题思路

  • 在python中可以直接把list转为set,因为set是去重的,然后做一个交集即可;
class Solution:
    def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
        a = set(nums1)
        b = set(nums2)
        re = a & b
        return list(re)
  • 记得要把去重后的set转为list返回;
  1. 快乐数(202)

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

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

解题思路

  • 一个正整数,求每个位置上的数组平方,其实就是不断除以10求余数;
  • 不断重复上面的过程,然后记录每一次的结果,利用set中元素不能重复的特性来判断是否陷入了无限循环;
class Solution:
    def isHappy(self, n: int) -> bool:
        def cal_happy(n):
            sum_ = 0
            while n:
                sum_ += (n%10)**2
                n = n//10
            return sum_
        records = set()

        while True:
            n = cal_happy(n)
            if n==1:
                return True
            if n in records:
                return False
            else:
                records.add(n)
  • 计算各个数字的和不难,主要是计算完了之后怎么保存记录?用数组还是set?根据题目的要求,肯定是set更好,因为可以很快的判断是否已经存在,这也是哈希表的常见用法;
  • 因为可能会无限循环,所以要想好循环终止的条件,要么是快乐数(返回true),要么就是循环(返回false);
  • while True这种循环一定要想好出口!
  1. 两数之和(1)

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target  的那 两个 整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。 你可以按任意顺序返回答案。

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

解题思路

  • 输入的是数组+目标值,需要的输出是数组的下标,所以要根据值来查询下标,而数组是根据下标来查询值,所以不能直接用数组解决;
  • 把值作为key,下标作为value,自然想到python中的dict,难的是怎么写循环;
  • python中怎么从一个list同时的到下标和值呢?enumerate函数!
  • 按照题目的意思是一定存在两个数的和等于target,所以不要多想!
class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        records = dict()

        for index, val in enumerate(nums):
            if target-val in records:
                return [index, records[target-val]]
            else:
                records[val]=index
  • 也可以写两个循环,就是先把nums转成dict,然后再去循环判断,但是会增加时间复杂度,所以一边转换,一边判断;

补充知识点

  1. 哈希表的概念

哈希表用的是数组支持按照下标随机访问数据的特性,所以哈希表其实就是数组的一种扩展,由数组演化而来。可以说,如果没有数组,就没有散列表。可以看参考【4】

  1. 哈希表的实现原理

可以看参考【3】,或者理解下图:

alt
  1. python中enumerate函数的用法

enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。

今日思考

  1. 为什么在有环的情况下快慢指针一定会在环中某个节点相遇?

想象两个同学在操作跑步。。

  1. 为什么存在环的时候,从头节点出发的指针一定与慢指针在环的入口相遇?

看参考【1】的数学推导。。。

参考

【1】代码随想录:https://programmercarl.com/
【2】set:https://www.runoob.com/python/python-func-set.html
【3】https://zhuanlan.zhihu.com/p/144296454
【4】https://zhuanlan.zhihu.com/p/107326081
【5】enumerate:https://www.runoob.com/python/python-func-enumerate.html

本文由 mdnice 多平台发布

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值