知识点
- 哈希表 / 散列表 (hash table):
什么时候想到用哈希法?当我们遇到了要快速判断一个元素是否出现在集合里的时候,就要考虑哈希法。但是哈希法也是牺牲了空间换取了时间,因为我们要使用额外的数组,set或者是map来存放数据,才能实现快速的查找。
遇到需要判断一个元素是否出现过的场景也应该第一时间想到哈希法。 - 哈希函数
- 哈希碰撞
两种解决方法:
1)拉链法
拉链法就是要选择适当的哈希表的大小,这样既不会因为数组空值而浪费大量内存,也不会因为链表太长而在查找上浪费太多时间。
2)线性探测法
使用线性探测法,一定要保证 tableSize 大于 dataSize 。 我们需要依靠哈希表中的空位来解决碰撞问题。 - 常见的三种哈希结构:
1)数组
2)set
3)map
Leetcode 242. 有效的字母异位词
题目链接:242. 有效的字母异位词
思路:
一开始想用map,后面想了下,用数组更简单。因为只有小写英文字母,数组长度固定。map的那些常用函数名有点忘了。
解题:成功
代码实现
class Solution {
public boolean isAnagram(String s, String t) {
int[] counts = new int[26];
for(int i = 0; i < s.length(); i++){
counts[s.charAt(i) - 'a']++;
}
for(int i = 0; i < t.length(); i++){
counts[t.charAt(i) - 'a']--;
}
for(int count : counts){
if(count != 0){
return false;
}
}
return true;
}
}
这道题目,可以感受到数组用来做哈希表给我们带来的便利之处。
Leetcode 349. 两个数组的交集
题目链接:349. 两个数组的交集
思路:
题很简单,但是对于set的常用函数不够熟悉。例如add,contains,循环遍历等。
解题:成功
代码实现
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
Set<Integer> set = new HashSet<>();
Set<Integer> intersect = new HashSet<>();
for(int i : nums1){
set.add(i);
}
for(int i : nums2){
if(set.contains(i)){
intersect.add(i);
}
}
int size = intersect.size();
int[] res = new int[size];
int i = 0;
for(int num : intersect){
res[i] = num;
i++;
}
return res;
}
}
本题还可以使用数组来作为哈希表,因为数值规定都在0~1000之间,这样效率可能更高一些,毕竟set需要先计算 hash 值再存储。
Leetcode 202. 快乐数
题目链接:202. 快乐数
思路:
关键在于要理解为什么会想到用哈希法。题目说了可能无限循环,这相当于判断一个元素是否出现在集合里,此时就要考虑哈希法了。
解题:成功
代码实现
class Solution {
public boolean isHappy(int n) {
Set<Integer> set = new HashSet<>();
int sum = n;
while(!set.contains(sum)){
set.add(sum);
int b = sum;
sum = 0;
while(b != 0){
int a = b % 10;
b = b / 10;
sum += a * a;
}
if(sum == 1){
return true;
}
}
return false;
}
}
可以把求和的那一段代码写成一个独立的方法
Leetcode 1. 两数之和
题目链接:1. 两数之和
思路:
关键在于理解为什么会想到用哈希法,为什么用map结构。
解题:成功
代码实现
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
for(int i = 0; i < nums.length; i++){
int a = target - nums[i];
if(map.containsKey(a)){
return new int[]{i, map.get(a)};
}
map.put(nums[i], i);
}
return new int[0];
}
}