哈希表set,map

本文介绍了哈希表的基础知识,包括哈希函数和解决哈希碰撞的方法。讨论了数组、set、map作为哈希容器的区别,指出unordered_set和unordered_map在处理无序元素时的优势。通过实例解析了如何利用哈希表解决快乐数判断、两数之和、三数之和以及子串拼接问题,强调了哈希表在快速查找和去重中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

哈希表基础要点

hash table : 根据键值(key)查找value。哈希函数,哈希碰撞问题解决->拉链法/线性探测法。

数组/set/map是常用的哈希容器,因此定义时要指定元素类型。区别为:

首先,通过将键值映射到数组下标,数组可以当做哈希表使用,但下标值不宜太大,过大的下标意味着要申请很多空间,极易造成浪费。

set在c++的标准中又定义了3种模板:set<>,mulitset<>,unordered_set<>。unordered_set底层实现为哈希表,元素是无序的,因此从构建和查找都是最简便的,处理无序元素时作为首选。set和multiset是有序的集合,构建时消耗更多资源。

map结构为:map<key, value>,也分为map<>,multimap<>,unordered_map<>。unordered_map是首选。

更多的实现知识后面再补充。

问题:给定一个正整数n,判断n是否为快乐数,原则为:将n的各个位上的数的平方相加记为sum,循环这个步骤,直到sum=1,为快乐数;或者循环下去,不是快乐数。

要求解这个问题,需要解决其中两个步骤,1.计算sum,sum的计算比较好解决。2.如何判断是否陷入无限循环?在步骤1中,从一个旧的sum计算出一个新sum,循环中会出现很多个sum记录,如果出现重复的sum值,则意味着进入了无线循环。因此需要一个容器来记录出现过的sum值,这个容器要求能够快速查找,不重复࿰

### Java 中哈希表Set 的实现及用法 #### 1. 哈希表的基本概念 Java 中的哈希表是一种基于键值对的数据结构,它利用哈希函数来映射键到特定的位置上,从而支持高效的插入、删除查找操作。这种数据结构的核心在于如何设计合理的哈希函数以及处理可能发生的哈希冲突[^1]。 #### 2. 哈希表的工作原理 当向哈希表中插入一个键值对时,会先调用键对象的 `hashCode()` 方法获取其哈希码,再通过某种算法将其转换为数组索引位置。如果多个不同的键被映射到了同一个索引位置,则会发生哈希冲突。解决这一问题通常采用链地址法或开放寻址法等策略[^4]。 以下是使用 HashMap 插入查询的一个简单例子: ```java import java.util.HashMap; public class Example { public static void main(String[] args) { HashMap<String, Integer> map = new HashMap<>(); map.put("Alice", 25); map.put("Bob", 30); System.out.println(map.get("Alice")); // 输出 25 } } ``` #### 3. HashSet 的基本概念 `HashSet` 是一种不保存重复元素的集合类型,在内部实际上是通过 `HashMap` 来实现的。每当尝试向 `HashSet` 添加新元素时,都会检查该元素是否已经存在;这一步骤依赖于元素自身的 `equals()` `hashCode()` 方法[^3]。 下面是一个简单的 `HashSet` 使用案例: ```java import java.util.HashSet; public class ExampleSet { public static void main(String[] args) { HashSet<Integer> set = new HashSet<>(); set.add(1); set.add(2); set.add(2); // 不会产生任何效果,因为不允许重复 System.out.println(set.size()); // 输出 2 } } ``` #### 4. 关于 hashCode() 的重要性 为了使自定义类的对象能够在基于哈希的集合(如 `HashMap`, `HashSet`)中正常工作,必须重写 `hashCode()` `equals()` 方法。这是因为这些集合依靠这两个方法判断两个对象是否相等并决定它们应存放在哪里[^2]。 例如,考虑如下代码片段展示了一个未正确覆盖上述两者的潜在风险: ```java class Person { private String name; public Person(String name){ this.name = name; } @Override public boolean equals(Object o){ if(o instanceof Person && ((Person)o).name.equals(this.name)){ return true; } return false; } // 如果忘记提供此方法... } // 测试部分省略... ``` 这里如果没有适当定义 `hashCode()` 函数的话,即使实现了 `equals()` 判断逻辑也无济于事——由于默认继承自 Object 类的行为可能导致完全不一样的散列值分配给实际上应该视为同一实体的不同实例们之间相互独立对待起来。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值