力扣每周专题-哈希表
哈希表定义及其常用用法
简单来说,哈希表是采用一种特定函数,将值散列到某一个下标中。
一个好的散列函数对于哈希表来说特别重要,最好是能将所有值唯一映射到一个位置,如果发生冲突,那么就需要冲突解决函数来解决冲突。
Java中的HashMap
- 定义
HashMap在util包中:import java.util.HahMap;
它是一个散列表,里面存储的内容为以<key,value>的键值对,键和值的数据类型可以是基本数据类型,也可以是组合类型。
- 创建和初始化
创建:HashMap<kType,vType> mapName = new HashMap<>();
- 常用方法
增加一对键值 | put(key,value) |
---|---|
删除某一对键值 | remove(key) |
更改某一个键对应的值 | replace(key , newValue) |
查询某一个键对应的值 | get(key) |
查询某一个键是否存在 | boolean containsKey(key) |
查询某个值是否在 | boolean containsValue(value) |
删除所有键值对 | void clear() |
复制哈希表的副本 | HasMap<> clone() |
判断哈希表是否为空,如果为空返回true | boolean isEmpty() |
返回哈希表中键值对数量 | int size() |
将一个Map对象或者其继承类对象添加到Hash Map | void putAll(Map o) |
如果Hash Map中不包含这个键,则将该键值对插入Hash Map | vType putIFAbsent(key ,value) |
将Hash Map中所有的键值对替换成给定的函数关系 | replaceAll( (key,value)->fun ) |
对其中的每对键值执行相同的方法 | map.forEach( (key,value)->{函数体}) |
返回其中的Key的集合 | set keySet() |
返回其中value的集合 | set values() |
对其中的指定的key对应的值重新计算 | vType compute(key , (key,value)->fun) |
对其中指定的键如果存在的话采用重新计算的值,不存在的话则新建这个key,因此重新计算的函数不能包含oldValue | computeIFAbsent(key , (key,value)->fun) |
重新计算指定key对应的值,前提是该key存在 | computeIFPresent(key,(key,value)->fun) |
- 遍历
方法一:采用for-each
for (vType vo : map.keySet){ map.get(vo)}
方法二:采用迭代器
Iterator it = map.entrySet().iterator();
while(it,hasNext()){}
Java中的HashSet
- 定义
HashSet是基于HashMap实现的一个无序且不允许有重复元素的集合
它不是线程安全的,多个用户同时修改时就会引发错误
- 创建和初始化
import java.util.HashSet;
HashSet<oType.> set = new HashSet<>();
- 常用方法
添加元素,注意重复元素不会添加 | void add(value) |
---|---|
判断某某元素是否存在集合中 | boolean contains(value) |
删除元素,删除成功返回true | boolean remove(value) |
删除所有元素 | clear() |
获取元素个数 | int size() |
获取迭代器 | Iterator<oType.> iterator() |
判空 | boolean isEmpty() |
- 遍历
方法一:for-each
for(oType name : hashset){}
方法二:迭代器Iterator
Iterator<oType.> it = hashset.iterator();
while(it.hasNext()){ it.next();}
参考来源:https://www.runoob.com/java/java-hashset.html
力扣原题
1.原题141/142:判断有环-通过加入结点,判断节点是否已被访问过
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
/**方法一:采用双指针 -快慢指针,如果有环那么在为达到尾部时两个指针会相遇
方法二:集合-每次都把以访问的结点加入集合中,每一个新节点判断是否在集合中 */
public class Solution {
public boolean hasCycle(ListNode head) {
if(head == null)
return false;
HashSet<ListNode> set = new HashSet<>();
ListNode current = head;
while(current!=null){
if(set.contains(current))
return true;
else
set.add(current);
current = current.next;
}
return false;
}
}
2.力扣原题:2325
class Solution {
public String decodeMessage(String key, String message) {
/使用一个哈希表:给key的每个字母进行排序。。使用一个num来指定 这是第几个字母
//为了避免重复添加,先判断该字母在不在哈希表中,只有不在的情况才添加
//得到解密哈希之后,进行解密-注意key message中空格不计
HashMap<Character,Character> key_map = new HashMap<>();
char num = 'a';
for(char ch : key.toCharArray()){
if(!Character.isLetter(ch)) //判断是不是字母
continue;
if(!key_map.containsKey(ch)){
key_map.put(ch,num);
num++;
//提升技巧1:因为最多只有26个字母。因此得到所有字母的对照表之后就可以停止了
if(key_map.size() == 26)
break;
}
}
StringBuffer str_buffer = new StringBuffer(message);
for(int i=0;i<str_buffer.length();i++){
char ch = str_buffer.charAt(i);
if(!Character.isLetter(ch))
continue;
str_buffer.setCharAt(i,key_map.get(ch));
}
return str_buffer.toString();
}
}
总结:HashMap可以保存历史信息和遍历过程,因此用在需要用到历史信息的题目中
或者是 需要统计信息的题目中
Map结构保存的历史信息可以是值或者是链表的地址,如力扣141题目。
Map统计信息,比如力扣2325题
Hash Set不允许重复元素,因此用在中间计算可能出现重复值的情况