哈希表算法
哈希表是根据关键码的值而直接进行访问的数据结构。其实直白来讲其实数组就是一张哈希表。
当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法
数值的范围小,可用数组充当哈希表
当明确知道需要定义一个不是很大的集合时,可以直接用数组充当哈希表,不必使用std::unordered_set等。
有效的字母异位词
Leetcode:242.有效的字母异位词
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
示例 1: 输入: s = “anagram”, t = “nagaram” 输出: true
示例 2: 输入: s = “rat”, t = “car” 输出: false
说明: 你可以假设字符串只包含小写字母
思路:由于给定的字符串是小写英文字母,总共有26个,所以定义一个26大小的数组即可,然后把字符减去’a’,把字母映射到数组中。
1 | func isAnagram(s string, t string) bool { |
数值的范围大,用真正的哈希表set
使用数组来做哈希的题目,是因为题目都限制了数值的大小,而且如果哈希值比较少、特别分散、跨度非常大,使用数组就造成空间的极大浪费。
当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法了
两个数组的交集
Leetcode:349.两个数组的交集
给定两个数组 nums1
和 nums2
,返回它们的交集 。输出结果中的每个元素一定是唯一的。我们可以不考虑输出结果的顺序。
示例 1:
1 | 输入:nums1 = [1,2,2,1], nums2 = [2,2] |
示例 2:
1 | 输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4] |
思路分析:使用哈希表解决数值范围大的问题,C++中可以使用unordered_set
,底层是哈希表,读写效率最高,并且不需要排序;而go使用map[int]struct{}
替代哈希表。
1 | func intersection(nums1 []int, nums2 []int) []int { |
快乐数
Leetcode:202.快乐数
编写一个算法来判断一个数 n 是不是快乐数。
「快乐数」定义为:
对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
然后重复这个过程直到这个数变为 1,也可能是 *无限循环* 但始终变不到 1。
如果 *可以变为* 1,那么这个数就是快乐数。
如果 n 是快乐数就返回 true ;不是,则返回 false 。
*示例 1:*
****输入:****19
****输出:****true
*解释:*
1^2 + 9^2 = 82
8^2 + 2^2 = 68
6^2 + 8^2 = 100
1^2 + 0^2 + 0^2 =
思路:题目中说了会无限循环,那么也就是说求和的过程中,sum重复出现,就不是快乐数,当sum等于1时,就是快乐数!当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法了。所以此题就是把sum值存在哈希表里,然后每次循环查询哈希表里是否有这个值,和判断sum值是否等于1。
1 | func isHappy(n int) bool { |
- 时间复杂度: O(logn)
- 空间复杂度: O(logn)
数值的范围大,用真正的哈希表map
两数之和
Leetcode:两数之和
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
思路:哈希表key代表值,value代表下标,在哈希表中查找key为target-nums[i]的值,找到了,就直接返回两个的下标,找不到则插入哈希表里。
1 | func twoSum(nums []int, target int) []int { |
- 时间复杂度: O(n)
- 空间复杂度: O(n)