这次主要总结“哈希表”的题目和用法。
定义及概念
哈希表:根据关键码的值而直接进行访问的数据结构。
哈希表(Hash Table)是一种通过哈希函数将键映射到固定大小的数组中的数据结构。它通常用于快速查找、插入和删除操作。哈希表是实现关联数组(或字典、映射)的一种常见方式,能够在常数时间内完成大部分操作(即时间复杂度接近O(1)),尽管在某些情况下可能会退化为O(n)
主要作用:快速判断一个值是否在表中
当我们想使用哈希法来解决问题的时候,我们一般会选择如下3种数据结构。
- 数组
- set (集合)
- map(映射)
在C++中,set 和 map 分别提供以下三种数据结构,其底层实现以及优劣如下表所示(表引自代码随想录):
| 集合 | 底层实现 | 是否有序 | 数值是否可以重复 | 能否更改数值 | 查询效率 | 增删效率 |
|---|---|---|---|---|---|---|
| std::set | 红黑树 | 有序 | 否 | 否 | O(log n) | O(log n) |
| std::multiset | 红黑树 | 有序 | 是 | 否 | O(logn) | O(logn) |
| std::unordered_set | 哈希表 | 无序 | 否 | 否 | O(1) | O(1) |
std::unordered_set底层实现为哈希表,std::set 和std::multiset 的底层实现是红黑树,红黑树是一种平衡二叉搜索树,所以key值是有序的,但key不可以修改,改动key值会导致整棵树的错乱,所以只能删除和增加。
| 映射 | 底层实现 | 是否有序 | 数值是否可以重复 | 能否更改数值 | 查询效率 | 增删效率 |
|---|---|---|---|---|---|---|
| std::map | 红黑树 | key有序 | key不可重复 | key不可修改 | O(logn) | O(logn) |
| std::multimap | 红黑树 | key有序 | key可重复 | key不可修改 | O(log n) | O(log n) |
| std::unordered_map | 哈希表 | key无序 | key不可重复 | key不可修改 | O(1) | O(1) |
Java里的HashMap, TreeMap同理,其中TreeMap是有序的。
例题:组成字符串ku的最大次数
给定一个字符串 ss,该字符串中只包含英文大小写字母。你需要计算从字符串中最多能组成多少个字符串 "ku"。每次可以随机从字符串中选一个字符,并且选中的字符不能再使用。字符串中的字符大小写可以忽略,即大写和小写字母视为相同。
例如,输入 "AUBTMKAxfuu",从中最多能组成 1 个 "ku"。
很简单,遍历k和u并存储个数就行
`
import java.util.HashMap;
public class Main {
public static int solution(String s) {
// write code here
HashMap<String, Integer> map=new HashMap<>(0);
for(int i=0;i<s.length();i++)
{
if(s.charAt(i)=='k'|s.charAt(i)=='K')
{
if(map.containsKey("k"))
{
int num=map.get("k");
map.put("k",num+1);
}
else
map.put("k",1);
}
if(s.charAt(i)=='u'|s.charAt(i)=='U')
{
if(map.containsKey("u"))
{
int num=map.get("u");
map.put("u",num+1);
}
else
map.put("u", 1);
}
}
if(!map.containsKey("k") |!map.containsKey("u"))
return 0;
return Math.min(map.get("k"), map.get("u"));
}
public static void main(String[] args) {
System.out.println(solution("AUBTMKAxfuu") == 1);
System.out.println(solution("KKuuUuUuKKKKkkkkKK") == 6);
System.out.println(solution("abcdefgh") == 0);
}
}
————————————————