DAY6 哈希表、LeetCode242、349、202、1
1.哈希表
- 哈希表:根据数组的索引下标直接访问数组中元素的数据结构。
- 哈希函数:根据 hashcode 将数据映射为索引下标的一种方法。
- 哈希碰撞:不同的数据映射到了同一个索引数值;解决方法:拉链法、线性探测法。
- 常见的三种哈希结构:数组、set、map。
2.LeetCode242:有效的字母异位词
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。**注意:**若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。
题解:哈希数组
新建一个长度为26的数组record,初始化为0。遍历s的字母,对应的数组值加一。比如:字母为a,record[0]++,字母为z,record[25]++。s遍历结束后遍历t,相对应的数组值减一。最后判断record数组是否全为0,若是则说明s和t是字母异位词;若不是则说明s和t不是字母异位词。
int[] record = new int[26];
for(int i = 0; i < s.length(); i++){
record[s.charAt(i) - 'a']++;
}
for(int i = 0; i < t.length(); i++){
record[t.charAt(i) - 'a']--;
}
for(int count: record){
if(count != 0){
return false;
}
}
return true;
3.LeetCode 349:两个数组的交集
给定两个数组 nums1
和 nums2
,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。
题解:set 和 哈希数组
- 3.1 用set1集合来记录nums1中的数,set会自动去重。然后遍历nums2中的数,和set1中的数对比,如果set1中出现过了就加入到setRes中。setRes中的数就是nums1和nums2的交集。
if(nums1 == null || nums1.length == 0 || nums2 == null || nums2.length == 0){
return new int[0];
}
Set<Integer> set1 = new HashSet<>();
Set<Integer> resSet = new HashSet<>();
for(int num: nums1){
set1.add(num);
}
for(int num: nums2){
if(set1.contains(num)){
resSet.add(num);
}
}
int[] arr = new int[resSet.size()];
int index = 0;
for(int i : resSet){
arr[index++] = i;
}
return arr;
- 3.2 因为题目给定了数组大小不会超过1000,所以可以定义两个大小为1000的数组hash1 和 hash2,分别用来保存nums1 和nums2中的数。遍历nums1,在hash1中以此数为下标的位置上 +1,即
hash1[i]++
;nums2同理。最后遍历hash1 和hash2,同一个下标处,两数组均不为0则此数为两数组的交集,即hash1[i] > 0 && hash2[i] > 0
。
int[] hash1 = new int [1000];
int[] hash2 = new int [1000];
for(int i : nums1)
;
for(int i : nums2)
hash2[i]++;
List<Integer> resList = new ArrayList();
for(int i = 0; i < 1000; i++){
if(hash1[i] > 0 && hash2[i] > 0){
resList.add(i);
}
}
int[] arr = new int[resList.size()];
int index = 0;
for(int i : resList){
arr[index++] = i;
}
return arr;
4.LeetCode 202:快乐数
编写一个算法来判断一个数 n
是不是快乐数。如果 n
是 快乐数 就返回 true
;不是,则返回 false
。
「快乐数」 定义为:
- 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
- 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
- 如果这个过程 结果为 1,那么这个数就是快乐数。
题解:set集合(不可重复的性质)
用一个set集合来记录每次替换的数,若该数不为1且不在set集合中,则将该数放入set集合;若该数已经在set中,说明进入了无限循环,则n不是快乐数;若该数为1,则n是快乐数。
public boolean isHappy(int n) {
Set<Integer> record = new HashSet<>();
while(n != 1 && !record.contains(n)){ //第一次传入的是n,第二次开始传入的就是res,即每个位置上的数字平方和
record.add(n);
n = getNextNumber(n);
}
return n == 1;
}
//求每个位置上的数字的平方和的函数
private int getNextNumber(int n){
int res = 0;
while(n > 0){
res += (n % 10) * (n % 10);
n = n /10;
}
return res;
}
5.LeetCode 202:两数之和
给定一个整数数组 nums
和一个整数目标值 target
,请你在该数组中找出 和为目标值 target
的那 两个 整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。你可以按任意顺序返回答案。
题解:map,储存key 和 value
- 遍历数组,将遍历过的数存入map,key为数值,value为该数在数组中的下标,因为最终返回结果为下标。每遍历一个数,就在map中查找有无
target - nums[i]
,若有则将这两个数的下标值存入res数组,最终返回res数组。
int[] res = new int[2];
Map<Integer,Integer> map = new HashMap<>();
for(int i = 0; i < nums.length; i++){
int temp = target - nums[i];
if(map.containsKey(temp)){
res[0] = map.get(temp);
res[1] = i;
break; //找到一组符合条件的就可以结束
}
map.put(nums[i],i);//key为数值,value为下标
}
return res;