HashMap → 直接用 map#
// 声明并初始化
m := make(map[string]int)
// 常用操作
m["apple"] = 1 // 写入
v := m["apple"] // 读取,不存在返回零值
v, ok := m["apple"] // 安全读取,ok=false 表示不存在
delete(m, "apple") // 删除
// 遍历
for k, v := range m {
fmt.Println(k, v)
}HashSet → 用 map[T]struct{}#
Go 没有内置 Set,惯用做法是 value 用 struct{}{}(占 0 字节):
set := make(map[int]struct{})
// 添加
set[1] = struct{}{}
set[2] = struct{}{}
// 判断是否存在
_, ok := set[1] // ok = true
_, ok := set[99] // ok = false
// 删除
delete(set, 1)也有人图省事用
map[int]bool,但struct{}更省内存
LeetCode 常见场景#
① 统计频次(HashMap)
func twoSum(nums []int, target int) []int {
seen := make(map[int]int) // 值 -> 下标
for i, v := range nums {
if j, ok := seen[target-v]; ok {
return []int{j, i}
}
seen[v] = i
}
return nil
}② 去重 / 判断是否存在(HashSet)
func containsDuplicate(nums []int) bool {
set := make(map[int]struct{})
for _, v := range nums {
if _, ok := set[v]; ok {
return true // 已存在,有重复
}
set[v] = struct{}{}
}
return false
}③ 字符频次(数组代替 HashMap,更快)
// 只有小写字母时,用数组比 map 快很多
freq := [26]int{}
for _, c := range "hello" {
freq[c-'a']++
}对比总结#
| 类型 | 写入 | 查询 | 删除 | |
|---|---|---|---|---|
| HashMap | map[K]V |
m[k]=v |
v,ok:=m[k] |
delete(m,k) |
| HashSet | map[K]struct{} |
s[k]=struct{}{} |
_,ok:=s[k] |
delete(s,k) |
记住一点:查询一定要用 _, ok := m[k] 的双返回值形式,否则 key 不存在时只会返回零值,容易出 bug。