当我们需要快速判断一个元素是否出现在集合里,或者说一个元素是否出现过,则可以使用哈希法。
哈希法是一种以空间换时间的方法。
242.有效的字母异位词
数组其实就是一个简单哈希表,而且这道题目中字符串只有小写字符,那么就可以定义一个数组,来记录字符串s里字符出现的次数。对t中出现的字符映射哈希表索引上的数值再做-1的操作。最后看下record数组中元素是否全为0。若全为0,说明s和t是字符异位词,若不全0,则s和t不是字符异位词。
如果要用数组来做哈希的题目,则题目中需要限制数值的大小。而且如果哈希值比较少、特别分散、跨度非常大,使用数组就造成空间的极大浪费。
public boolean isAnagram(String s, String t) {
//字典解法 时间复杂度O(m+n)
int [] record = new int[26]; //使用哈希法,创建数组来存储元素
for(int i = 0;i < s.length();i++)
record[s.charAt(i)-'a']++; // 并不需要记住字符a的ASCII,只要求出一个相对数值就可以了
for(int j = 0;j < t.length();j++)
record[t.charAt(j)-'a']--;
for(int k = 0;k < 26;k++)
if(record[k] != 0) //若record数组存在不为0的元素,说明s和t每个字符出现的次数不相同
return false;
return true; //record数组中所有元素的值为0,说明s和t为字母异位词
}
349. 两个数组的交集
public int[] intersection(int[] nums1, int[] nums2) {
//由题意可得,元素不可重复且可以无序,因此用unordered_set结构
if(nums1 == null || nums1.length == 0 || nums2 == null || nums2.length == 0)
return new int [0];
Set<Integer> set1 = new HashSet<Integer>();
Set<Integer> resultSet = new HashSet<Integer>();
//遍历num1数组,将元素放入集合中
for(int i:nums1)
set1.add(i);
//遍历nums2数组,判断哈希表中是否存在该元素
for(int i:nums2)
if(set1.contains(i))
resultSet.add(i);
//转换成数组:另一个创建一个数组存放交集中的元素,最后返回数组
int [] arr = new int[resultSet.size()];
int j = 0;
for(int i:resultSet)
arr[j++] = i;
return arr;
}
202. 快乐数
根据观察,会有以下三种可能。
- 最终会得到 111。
- 最终会进入循环。
- 值会越来越大,最后接近无穷大。
但是第三种可能不会出现,因为假设这个数很大,但是在求各个位数的平方和后该数会变小,4位或4位以上的数字在每一步都会丢失一位,直到降到3位为止,所以不会发生无穷大的情况。
public boolean isHappy(int n) {
//创建集合record,判断某一元素是否出现过
Set<Integer> record = new HashSet<>();
//若n为1,表明是快乐数;若集合中存在n,表明出现了无限循环
while(n != 1 && !record.contains(n)){
record.add(n);
n = getNextNumber(n);
}
if(n == 1)
return true; //最终变为1,表明为快乐数
else
return false; //n不为1,说明是无限循环,始终变不到1
}
//计算每个位置上的数字平方和,将该数替换掉
public int getNextNumber(int n){
int res = 0;
while(n > 0){
int temp = n%10;
res += temp * temp;
n = n/10;
}
return res;
}
1. 两数之和
在本题中,要掌握的函数是containsKey(Object key)、get()以及put()函数。
如何判断一个Map中是否包含某个键值对呢?Java中提供了一个方法containsKey,用于判断Map中是否包含指定的键。
get方法是Map接口中用于获取键所映射的值的方法,get(Object key)。
在Java中,我们通常会使用Map作为数据结构来存储一些键值对。而其中最常用的方法就是put()方法,它可以用来往Map中添加一个键值对。map.put("key1", "value1")
//因为需要查找值key及其下标value,因此用map
public int[] twoSum(int[] nums, int target) {
int [] res = new int [2]; //存放返回的下标值
Map<Integer,Integer> map = new HashMap<>(); //因为map有key和value,可以用来存放元素值及其下标索引
for(int i = 0;i < nums.length;i++){
int temp = target - nums[i];
if(map.containsKey(temp)){ //说明map中有元素值与nums[i]相加后为target
res[0] = i;
res[1] = map.get(temp); //得到key为temp的value值
}
map.put(nums[i],i); //若剩下的元素值不在map中,则将nums[i]加入map中
}
return res;
}