mirror of
https://github.com/krahets/hello-algo.git
synced 2026-07-21 19:06:11 +00:00
102 lines
4.2 KiB
Markdown
102 lines
4.2 KiB
Markdown
# 练习
|
||
|
||
## 知识巩固
|
||
|
||
### 发生哈希冲突后怎样查找
|
||
|
||
一个哈希表有 5 个桶,哈希函数为 $h(x)=x \bmod 5$,冲突时把元素依次放进该桶的列表中。
|
||
依次插入 `[1, 6, 11, 7]`:
|
||
|
||
<!-- numbered-subquestions -->
|
||
|
||
1. 写出 0~4 号桶中的内容;
|
||
2. 查找 6 时会先进入哪个桶,并依次检查哪些元素?
|
||
3. 根据第 1 问写出的桶内容,后插入的元素是否覆盖了先插入的元素?结合这种冲突处理方式说明理由。
|
||
|
||
??? success "参考答案"
|
||
|
||
1. 因为 $1\bmod5=6\bmod5=11\bmod5=1$,而 $7\bmod5=2$,各桶为:
|
||
|
||
```text
|
||
0: []
|
||
1: [1, 6, 11]
|
||
2: [7]
|
||
3: []
|
||
4: []
|
||
```
|
||
|
||
2. 查找 6 时先进入 1 号桶,再依次比较 1、6,第二次比较时找到目标。
|
||
|
||
3. 哈希值相同只表示它们落入同一个桶,并不表示这些元素相等。链式地址把冲突元素都保存在桶内,
|
||
查询时再逐个比较,因此 1、6、11 不会互相覆盖。
|
||
|
||
### 哈希表扩容后元素去哪儿
|
||
|
||
一个使用链式地址的哈希表原有 5 个桶,哈希函数为 $h(x)=x\bmod5$。
|
||
键 `[1, 6, 11]` 都在 1 号桶中。
|
||
|
||
现在把哈希表扩容为 7 个桶,哈希函数相应变为 $h(x)=x\bmod7$:
|
||
|
||
<!-- numbered-subquestions -->
|
||
|
||
1. 分别计算 1、6、11 的新桶号。
|
||
2. 扩容后哪些桶中有元素?
|
||
3. 扩容时能否把原来 1 号桶中的列表原样复制到新的 1 号桶?结合第 1、2 问的结果说明理由。
|
||
|
||
??? success "参考答案"
|
||
|
||
1. 新桶号分别为:
|
||
|
||
- $1\bmod7=1$;
|
||
- $6\bmod7=6$;
|
||
- $11\bmod7=4$。
|
||
|
||
2. 1 号桶保存 1,4 号桶保存 11,6 号桶保存 6。三个键不再挤在同一个桶中。
|
||
|
||
3. 不能原样复制。桶号由“键对桶数取余”得到。桶数从 5 变成 7 后,同一个键的新桶号可能改变,
|
||
因此必须重新计算每个键的位置。若把旧的 1 号桶原样复制过去,之后按新公式查找 6 和 11 时,
|
||
会分别前往 6 号桶和 4 号桶,从而找不到它们。
|
||
|
||
### 删除 6 后还能找到 11 吗
|
||
|
||
一个哈希表有 5 个位置,索引为 `0~4`,哈希函数为 $h(x)=x\bmod5$。
|
||
发生冲突时,从哈希函数算出的索引开始,向右寻找第一个空位。
|
||
|
||
依次插入 `[1, 6, 11]`:
|
||
|
||
<!-- numbered-subquestions -->
|
||
|
||
1. 三个数最终分别放在哪个索引?
|
||
2. 查找 11 时,会依次检查哪些索引?
|
||
3. 如果删除 6 时直接把它的位置改成“从未使用的空位”,而查找遇到空位就停止,
|
||
再查找 11 时会发生什么?这个查找结果是否正确?如果有问题,应怎样避免?
|
||
|
||
??? success "参考答案"
|
||
|
||
1. 1 放在索引 1。6 也映射到索引 1,发生冲突后放在索引 2。
|
||
11 同样从索引 1 开始,依次跳过已占用的索引 1、2,最终放在索引 3。
|
||
|
||
2. 查找 11 时依次检查索引 `1、2、3`,在索引 3 找到它。
|
||
|
||
3. 如果把索引 2 改成表示“从未使用”的空位,查找 11 时检查索引 1 后就会在索引 2 停止,
|
||
从而错误地认为 11 不存在。删除时应留下“已删除”标记:
|
||
查找遇到该标记时继续检查下一个索引(越过索引 4 后回到索引 0),而以后的插入仍可重新使用这个位置。
|
||
|
||
## 编程练习
|
||
|
||
### 比较两个字符串的字符组成
|
||
|
||
给定两个只含小写英文字母的字符串 `s` 和 `t`。
|
||
可以任意调整 `s` 中字符的位置,但不能添加、删除或替换字符。
|
||
|
||
请判断调整后能否得到 `t`;可以则返回 `true`,否则返回 `false`。
|
||
请使用哈希表记录各字母的出现次数,不对字符串中的字符排序。
|
||
|
||
??? tip "解题提示"
|
||
|
||
1. 两个字符串长度不同,它们的字符组成一定不同
|
||
2. 用哈希表记录每种字母的数量;扫描 s 时把对应计数加 1
|
||
3. 扫描 t 时把对应计数减 1;所有计数最终都为 0,字符组成才相同
|
||
|
||
[LeetCode](https://leetcode.cn/problems/valid-anagram/){ .rounded-button .exercise-button target="_blank" rel="noopener noreferrer" } [题目解析](https://leetcode.cn/problems/valid-anagram/solutions/2362065/242-you-xiao-de-zi-mu-yi-wei-ci-ha-xi-bi-cch7/){ .rounded-button .exercise-button target="_blank" rel="noopener noreferrer" }
|