哈希表基础
定义:哈希表中关键码就是数组的索引下标,然后通过下标直接访问数组中的元素。
用途:快速判断一个元素是否存在在一个集合中。
哈希函数:把关键吗转化为数组的索引。
哈希碰撞:集合中的关键吗元素的内容相同,在哈希表中映射的索引下标相同时候,用拉链法和线性探测法解决。
拉链法:哈希表中存放链表的头结点,用链表连接两个索引相同的关键码元素。
线性探测法:产生冲突的位置,放了其中一个元素,就向下寻找一个空位来存放冲突的数据。
常见的三种哈希结构:数组、集合(set)和映射(map)。
1)拉链法(链表太长会拉长搜索的时间)
2)线性探测
242.有效的字母异位词
题目链接:. - 力扣(LeetCode)
题目讲解:代码随想录
class Solution {
public boolean isAnagram(String s, String t) {
//存放二十六个字母的表
int[] hash = new int[26];
//判断长度是否合法
if(s.length() != t.length()) return false;
//把s存入hash表
for(int i = 0;i < s.length();i++){
hash[s.charAt(i) - 'a']++;
}
//用t在hash表中验证
for(int i = 0;i < t.length();i++){
if(--hash[t.charAt(i) - 'a'] < 0){
return false;
}
}
return true;
}
}
383.赎金信
题目链接:. - 力扣(LeetCode)
题目讲解:代码随想录
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
//存放二十六个字母的哈希表
int[] hash = new int[26];
//把magazine数组存入哈希表
for(int i = 0; i < magazine.length();i++){
hash[magazine.charAt(i) - 'a']++;
}
//验证
for(int i = 0; i < ransomNote.length();i++){
if(--hash[ransomNote.charAt(i) - 'a']<0){
return false;
}
}
return true;
}
}
49.字母异位词分组 (?)
题目链接:. - 力扣(LeetCode)
题目类型:哈希表分组
List<>讲解:http://li-bonan.blog.163.com/blog/static/135564770201161722115862/
Map<>讲解:Java中的Map(如果想知道Java中有关Map的知识点,那么只看这一篇就足够了!)_java map-优快云博客
map.computeIfAbsent():【JAVA】computeIfAbsent_java computeifabsent-优快云博客
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
//新建一个哈希表m
Map<String,List<String>> m = new HashMap<>();
//从二维列表中遍历
for(String str : strs){
//将字符串转化为字符数组
char[] s = str.toCharArray();
//对字符数组进行排序
Arrays.sort(s);
//在哈希表m中寻找与s键值
//找到啦就添加str
//没找到则在哈希表针对这个键值创建一个列表,在新列表中加入str元素。
m.computeIfAbsent(new String(s),k -> new ArrayList<>()).add(str);
}
//返回哈希表中的值列表
return new ArrayList<>(m.values());
}
}
438.找到字符串中所有字母异位词
题目链接:. - 力扣(LeetCode)
题目思路:哈希表 + 滑动窗口(随着遍历扩大窗口,不符合条件时缩小窗口)
思路概述:
1)根据p串的长度建立两个长度相同的以二十六个小写字母为关键码的哈希表,其中一个是p串的哈希表,一个是在s串上滑动窗口的哈希表。
2)利用Arrays.equals()工具直接比较两个哈希表是否相同,相同哈希表则是子串的字母出现频次和p串相同,可以直接存储起始位置了;不同需要删掉子串头部的一个元素,进入一个新元素,再次进行工具的比较。
class Solution {
public List<Integer> findAnagrams(String s, String p) {
//获得俩串长度
int m = p.length();
int n = s.length();
//建立俩哈希表
int[] Hashp = new int[26];
int[] Hashs = new int[26];
//存放答案
List<Integer> ans = new ArrayList<Integer>();
//长度不等直接毙掉
if(n < m){
return ans;
}
//录入p串和s子串的哈希表
for(int i = 0;i < m ;i++){
Hashp[p.charAt(i) - 'a']++;
Hashs[s.charAt(i) - 'a']++;
}
if(Arrays.equals(Hashp,Hashs)){
ans.add(0);
}
//在s串上进行滑动窗口操作
for(int i = m;i < n;i++){
Hashs[s.charAt(i-m) - 'a']--;
Hashs[s.charAt(i) - 'a']++;
if(Arrays.equals(Hashp,Hashs)){
ans.add(i-m+1);
}
}
return ans;
}
}