- 代码随想录-哈希基础
-
- 哈希使用场景
- 当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法。
- 但是哈希法也是牺牲了空间换取了时间,因为我们要使用额外的数组,set或者是map来存放数据,才能实现快速的查找。
- 如果在做面试题目的时候遇到需要判断一个元素是否出现过的场景也应该第一时间想到哈希法!
-
242有效的字母异位词
- 代码随想录 (programmercarl.com)
-
第一印象
- 题目是需要解决已经出现过的字母的问题,可以考虑采用哈希法。可以利用字母做
key,出现次数做value的方法记录一个字符串,再通过另外一个字符串对应的字母的出现进行减一操作。如果全部归零则返回成功。 -
讲解观后感
- 在容器的选择上,简单的数组就可以满足本题的要求。字母可以映射为数组的下标。有26个就足够(只出现小写字母)。并且可以利用字母ascII码的转换
-
解题代码
-
func isAnagram(s string, t string) bool { list := [26]int{} for _,i := range s { list[i - rune('a')]++ } for _,i := range t { list[i - rune('a')]-- } return list == [26]int{} } -
349两个数组的交集
- 代码随想录 (programmercarl.com)
-
第一印象
- 方法类似于“有效的字母异位词”,也是先遍历第一个数组,将里面的元素存储起来。然后再遍历第二个数组进行比较。问题在于容器的选择。
-
讲解观后感
- 了解到
unordered_set非常适合不需要排序、不需要元素重复的场景。如果知道元素上限的话,也可以使用数组。 -
遇到问题
- 原因是遍历而第二个数组进行比较时,没有清除键值对,返回的数组出现重复数字
-
解题代码
-
func intersection(nums1 []int, nums2 []int) []int { set:=make(map[int]int,0) // 用map模拟set res:=make([]int,0) for _,v:=range nums1{ if _,ok:=set[v];!ok{ set[v]=0 } } for _,v:=range nums2{ //如果存在于上一个数组中,则加入结果集,并清空该set值 if _,ok:=set[v];ok{ res=append(res,v) delete(set, v) //不要忘记清空出现一次的结果 } } return res } - 需要注意使用
golang语言时需要用map来模拟set -
202快乐数
- 代码随想录 (programmercarl.com)
-
第一印象
- 题干中给出,当不是快乐数的时候,会陷入无限循环,因此我们只要记录出现的数字,并判定出现重复之前会不会出现1
-
讲解观后感
- 当需要的是无序不重复的结果时,还是选择
unordered_set。另外关于如何操作各个位数上的数字运算,也需要注意。 -
解题代码
-
func isHappy(n int) bool { cset := make(map[int]int,0) m := n for m!=1 { t:=0 for m>0 { t += (m%10) * (m%10) m = m/10 } m = t if cset[m] == 1 { return false } else { cset[m] = 1 } } return true } -
1两数之和
- 代码随想录 (programmercarl.com)
-
第一印象
- 因为一定有且只有一组答案,所以可以采用两次遍历按照目标寻找差值的方法搜索,复杂度为
O(n^2)。如果按照哈希的思路,可以在遍历过程中存储下标和目标值的方法。可以用值为key,下标为value. -
讲解观后感
- 根据我们的需要,选用
unordered_map是最佳的方案。再次强调判断何时需要用到哈希。 - 为什么会想到用哈希表
- 哈希表为什么用map
- 本题map是用来存什么的
- map中的key和value用来存什么的
-
解题代码
-
func twoSum(nums []int, target int) []int { s := make(map[int]int) for t,n:= range nums { if pre, ok := s[target - n];ok { return []int{t,pre} } else { s[n] = t } } return []int{} }