哈希表理论基础
文章链接
哈希表:哈希表是根据关键码的值而直接进行访问的数据结构(关键码就是数组的索引下标,然后通过下标直接访问数组中的元素)
哈希表解决的问题:一班用来判断一个元素是否出现在集合中
哈希函数
通过hashCode把名字转化为数值,一般hashcode是通过特定编码方式,可以将其他数据格式转化为不同的数值,这样就把学生名字映射为哈希表上的索引数字了。
哈希碰撞
即出现多个元素指向同一个索引
哈希碰撞解决方法
1.拉链法:(数组+链表)
线性探测法:
一定要保证tableSize大于dataSize。 我们需要依靠哈希表中的空位来解决碰撞问题
常见的哈希结构
- 数组
- set(HashSet,TreeSet)
- map(hashMap.TreeMap)
总结:
总结一下,当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法。
但是哈希法也是牺牲了空间换取了时间,因为我们要使用额外的数组,set或者是map来存放数据,才能实现快速的查找。
有效的字母异位词
题目链接:
视频链接:
学透哈希表,数组使用有技巧!Leetcode:242.有效的字母异位词
思路:
利用数组arr(size=26)存储字符串每个字符出现的次数,然后遍历另一个字符串,字符出现一次就arr对应-1,最后遍历arr数组,如果都是0说明就是有效的字母异位词
代码:
public static boolean isAnagram(String s, String t) {
int []arr=new int[26];
char[] char_s = s.toCharArray();
char[] char_t = t.toCharArray();
for (int i = 0; i <char_s.length ; i++) {
arr[char_s[i]-'a']++;
}
for (int i = 0; i <char_t.length ; i++) {
arr[char_t[i]-'a']--;
}
for (int i = 0; i <arr.length ; i++) {
if(arr[i]!=0){
return false;
}
}
return true;
}
两个数组的交集
题目链接:
视频链接:
学透哈希表,set使用有技巧!Leetcode:349. 两个数组的交集
思路:(主要考察,在需要去重操作 的时候用到set)
利用set对两个数组进行去重,然后遍历去重后的数组,利用set.contains方法看是否纯在相同元素
代码:
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
HashSet<Integer> set1 = new HashSet<>();
HashSet<Integer> set2 = new HashSet<>();
for (int i = 0; i < nums1.length ; i++) {
set1.add(nums1[i]);
}
for (int i = 0; i < nums2.length ; i++) {
if(set1.contains(nums2[i])){
set2.add(nums2[i]);
}
}
Iterator<Integer> iterator = set2.iterator();
int[]ans=new int[set2.size()];
int i=0;
while (iterator.hasNext()) {
Integer next = iterator.next();
ans[i++]=next;
}
return ans;
}
}
快乐数
题目链接;
思路:
根据题目利用循环进行模拟,由题目可以知道,重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1,所以利用set保存n,如果n已经存在,那么最后判断n是否等于1就知该数是不是快乐数
代码:
class Solution {
public int cal(int n){
int sum=0;
while (n>0){
int num=n%10;
sum+=num*num;
n/=10;
}
return sum;
}
public boolean isHappy(int n) {
HashSet<Integer> set = new HashSet<>();
while (n!=1&&!set.contains(n)){
set.add(n);
n=cal(n);
}
return n==1;
}
}
两数之和
题目链接:
思路:
本题呢需要一个集合来存放我们遍历过的元素,然后在遍历数组的时候去询问这个集合,某元素是否遍历过,也就是 是否出现在这个集合。
那么我们就应该想到使用哈希法了。
因为本题,我们不仅要知道元素有没有遍历过,还要知道这个元素对应的下标,需要使用 key value结构来存放,key来存元素,value来存下标,那么使用map正合适。
代码
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] ans = new int[2];
HashMap<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
if (map.containsKey(target - nums[i])) {
ans[1] = map.get(target-nums[i]);
ans[0] = i;
break;
}
map.put(nums[i], i);
}
return ans;
}
}