本系列是代码随想录算法训练营的学习笔记之day6,主要记录一下刷题的过程,以及核心知识点和一些值的记录的问题。
代码随想录的资源都是免费的,具体可以看参考链接【1】。
今日知识点
哈希表理论基础:
-
-
哈希表是根据关键码的值而直接进行访问的数据结构(比如python中的字典);
-
数组其实也是hash表,其key就是下标,value是对应的元素;
哈希函数
比如要查询一个同学在不在一个学校,我们只需要初始化把这所学校里学生的名字都存在哈希表里,在查询的时候通过索引直接就可以知道这位同学在不在这所学校里了。 将学生姓名映射到哈希表上就涉及到了hash function ,也就是哈希函数。
哈希函数的具体解释可以看参考【1】和参考【2】,简单理解就是通过哈希函数,可以获取key对应的数组中的下标,通过下标直接去索引。
-
如果两个key被映射到同一个哈希表的相同索引,就发生了哈希碰撞(解决方法见参考【1】或者自行百度。。进阶知识了。。);
今日题目
-
给定两个字符串 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
-
给定两个数组 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)
-
编写一个算法来判断一个数 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);
-
-
给定一个整数数组 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,然后再去循环判断,但是会增加时间复杂度,所以一边转换,一边判断;
补充知识点
-
哈希表用的是数组支持按照下标随机访问数据的特性,所以哈希表其实就是数组的一种扩展,由数组演化而来。可以说,如果没有数组,就没有散列表。可以看参考【4】
-
可以看参考【3】,或者理解下图:
-
enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。
今日思考
-
为什么在有环的情况下快慢指针一定会在环中某个节点相遇?
想象两个同学在操作跑步。。
-
为什么存在环的时候,从头节点出发的指针一定与慢指针在环的入口相遇?
看参考【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