hash表和数组

哈希表基本概念和结构

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<IntegerInteger> 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])
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值