哈希表基本概念和结构
hash表常用的有三种结构
- 数组
- set
- table
不同哈希结构特点和使用条件
数组作为哈希表
数组的大小是有限的,受到系统栈空间(不是数据结构的栈)的限制。
如果数组空间够大,但哈希值比较少、特别分散、跨度非常大,使用数组就造成空间的极大浪费。
// 简单创建一个数组进行运算就行,但是需要注意题目中给出的数组的长度,如果太长的话 就转而使用哈希set
int[] store = new int[26];
set作为哈希表
set是一个集合,里面放的元素只能是一个key
HashSet<String> sites = new HashSet<String>();
// 引入 HashSet 类
import java.util.HashSet;
public class RunoobTest {
public static void main(String[] args) {
//创建
HashSet<String> sites = new HashSet<String>();
//添加
sites.add("Google");
sites.add("Runoob");
sites.add("Taobao");
sites.add("Zhihu");
sites.add("Runoob"); // 重复的元素不会被添加
//移除
sites.remove("Taobao"); // 删除元素,删除成功返回 true,否则为 false
//删除集合中所有元素可以使用 clear 方法:
sites.clear();
//检查 hashMap 中是否存在指定的 key 对应的映射关系。
sites.containsKey()
//检查 hashMap 中是否存在指定的 value 对应的映射关系。
sites.containsValue()
//替换 hashMap 中是指定的 key 对应的 value。
sites.replace()
//打印
System.out.println(sites);
//如果要计算 HashSet 中的元素数量可以使用 size() 方法:
//可以使用 for-each 来迭代 HashSet 中的元素。
System.out.println(sites.size());
for (String i : sites) {
System.out.println(i);
}
}
}
map作为哈希表
当需要判断和返回多个值的时候,就需要用map
map是一种<key, value>的结构
可以用key保存数值,用value在保存数值所在的下标。
当我们要使用集合来解决哈希问题的时候,优先使用unordered_set,因为它的查询和增删效率是最优的,如果需要集合是有序的,那么就用set,如果要求不仅有序还要有重复数据的话,那么就用multiset。
// 创建 HashMap 对象 Sites
HashMap<Integer, String> Sites = new HashMap<Integer, String>();
// 添加键值对
Sites.put(1, "Google");
// 添加键值对
Sites.put("one", "Google");
//我们可以使用 get(key) 方法来获取 key 对应的 value:
System.out.println(Sites.get(3));
//我们可以使用 remove(key) 方法来删除 key 对应的键值对(key-value):
Sites.remove(4);
//删除所有键值对(key-value)可以使用 clear 方法:
Sites.clear();
//计算大小
System.out.println(Sites.size());
// 输出 key 和 value
for (Integer i : Sites.keySet()) {
System.out.println("key: " + i + " value: " + Sites.get(i));
}
// 返回所有 value 值
for(String value: Sites.values()) {
// 输出每一个value
System.out.print(value + ", ");
//对 hashMap 中指定 key 的值进行重新计算,如果不存在这个 key,则添加到 hasMap 中
Sites.computeIfAbsent();
//遍历 累加 value 值
//getOrDefault() 获取指定 key 对应的 value,如果找不到 key ,则返回设置的默认值
for(int num : nums) map.put(num, map.getOredfault(num,0) + 1);
//遍历每一个value值
for(Map.Entry<Integer,Integer> it : map.entrySet){};
自用看不懂的语法解释
//查找map中的key值 并对于指定key值进行重新计算 如果不存在该值 就将该值 重新加入到map 中
// k -> new ArrayList<>() 一种占位符的表示方式 因为value值 可以是多个 通过下行代码 进行添加,(mean:有一定的冲突存在,链式结构),所以 需要一个占位符 来进行占位
//map.get(key).add(s);
map.computeIfAbsent(key, k -> new ArrayList<>());
map.get(key).add(s);
//使用优先队列来实现最小树结构
PriorityQueue<Map.Entry<Integer, Integer>> pq = new PriorityQueue<>(
(a, b) ->
a.getValue() - b.getValue()
);
//该题 是347. Top K Frequent Elements 给定一个数列 求频率在k前的数组
// 在使用 map进行记数操作之后 使用最小二叉树 进行维护 这样的话 就可以保证 数列一直维持在k个数组中间
for (Map.Entry<Integer, Integer> it : map.entrySet()) {
pq.add(it);
if (pq.size() > k) pq.poll();
}
//注意map.entry --我们可以认为 Map.Entry是一个存储两个元素的元组——一个键和一个值 -- 所以遍历的时候需要使用entryset 函数 这也提供了一个遍历的方式
List<Character> charList = new ArrayList<Character>();
Set<Character> charSet = new HashSet<Character>();
**求数组中最长的连续数列**
因为对于时间复杂度有要求 所以不能使用sort来直接进行排序
sort 进行排序的时间复杂度是o(nlogn)
查找数列中所符合要求的数组 最方便的方法 是使用哈希表进行查询
所以 使用set建立数组
哈希表进行查询的时间复杂度 是o(n)
判断哈希表中数列是否是联系的 可以使用的前后所指向的元素进行判断
有点类似于 指针的算法 如果是开头字母的话 那数字的前指针就为空 而后指针式保持存在的
在做类似的题目的时候可以不是简单的使用定义去完成相关题目 而是辅助使用 本身数组或者是表格的排列特性进行
**判断数独矩阵的合理性**
数独矩阵 本身具有三个判断题条件
1. 矩阵的每行中不能存在 相同的数字 -- 使用哈希表存储相应的数字 如果说contains 相应的数字 就return false
2. 矩阵的每列中不能存在 相同的数字 和每行的判断条件一致
3. 矩阵的每个九宫格中不能存在 相同的数字 -- 九宫格的话 重点就是怎么确定矩阵的下标 将9个矩阵 的每一个看作是一个整体 下标的话 直接使用整除3 来进行判断
-java-
//block
for (int i = 0; i < rows; i = i + 3) {
for (int j = 0; j < cols; j = j + 3) {
if (!checkBlock(i, j, board)) {
return false;
}
}
}
return true;
}
public boolean checkBlock(int idxI, int idxJ, char[][] board) {
Set<Character> blockSet = new HashSet<>();
int rows = idxI + 3;
int cols = idxJ + 3;
for (int i = idxI; i < rows; i++) {
for (int j = idxJ; j < cols; j++) {
if (board[i][j] == '.') {
continue;
}
if (blockSet.contains(board[i][j])) {
return false;
}
blockSet.add(board[i][j]);
}
}
return true;
-python-
for r in range(9):
for c in range(9):
if board[r][c] == ".":
continue
if (
board[r][c] in rows[r]
or board[r][c] in cols[c]
or board[r][c] in squares[(r // 3, c // 3)]
):
return False
cols[c].add(board[r][c])
rows[r].add(board[r][c])
squares[(r // 3, c // 3)].add(board[r][c])