1. 今日收获:哈希表理论基础、字母异位词、数组交集、快乐数、两数之和
2. 哈希表理论基础:
(1)哈希算法通过原来的值来确定其存储位置
(2)应用场景:判断元素是否存在集合中;去除重复(set元素和map的键相同只会添加一次)
(3)常用的数据结构:数组(桶计数的思想,适合元素较少且连续的情况),set集合(适合元素数较多,或者元素不连续较分散的情况),map(key对应value)
3. 有效的字母异位词
题目链接:242. 有效的字母异位词 - 力扣(LeetCode)
思想:用长度为26的数组来存储a-z字母的出现次数,遍历一个字符串,如果出现则数组对应元素加1;遍历另外一个字符串,出现对应的字母则数组元素减1。最后比较数组的元素是否全为0
方法:
class Solution {
public boolean isAnagram(String s, String t) {
int[] capital = new int[26]; // 26个位置对应字母a-z出现的次数
for (int i=0;i<s.length();i++){
capital[s.charAt(i)-'a']++;
}
for (int i=0;i<t.length();i++){
capital[t.charAt(i)-'a']--;
}
// 如果数组的元素为0,对应字母数量相等
for (int i=0;i<capital.length;i++){
if (capital[i]!=0){
return false;
}
}
return true;
}
}
总结:因为小写字母a-z数量较少且连续,所以适合用数组来判断对应字母是否出现。另外可以直接用字符减去‘a’字符来对应数组下标。
4. 两个数组的交集
题目链接:349. 两个数组的交集 - 力扣(LeetCode)
思想:先遍历一个数组将其中的元素添加到set集合中,再遍历另外一个数组判断其元素是否出现在集合中,如果出现则是两个数组的交集。注意结果也需要去重。
方法:
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
// 首先遍历一个数组,利用集合去重其中的元素
HashSet<Integer> numSet = new HashSet<>();
HashSet<Integer> arr=new HashSet<>(); // 结果也需要去重
for (int i=0;i<nums1.length;i++){
if (!numSet.contains(nums1[i])){
numSet.add(nums1[i]);
}
}
// 判断集合中的元素是否同时存在nums2中
for (int i=0;i<nums2.length;i++){
if (numSet.contains(nums2[i])){
arr.add(nums2[i]);
}
}
// 遍历赋值返回数组
int[] result=new int[arr.size()];
int k=0;
for (int num: arr ){
result[k++]=num;
}
return result;
}
}
总结:因为本题要求结果也不能重复,所以首先用set集合存储结果,将set集合赋值给数组需要用增强for一个个赋值给数组的元素。
5. 快乐数
思想:不断地求数组各个位置数字的平方和,如果为1则是快乐数,如果重复了之前的结果就不是快乐数。
方法:
class Solution {
public boolean isHappy(int n) {
// 判断是否会无限循环
HashSet<Integer> numSet = new HashSet<>();
boolean flag=false;
while(true){
int temp=getSquar(n);
if (temp==1){ // 快乐数
flag=true;
break;
}else{ // 不是1
if (numSet.contains(temp)){ // 无限循环了
flag=false;
break;
}else{
numSet.add(temp);
n=temp;
}
}
}
return flag;
}
// 获取每个位置上的数字的平方和
public int getSquar(int num){
int result=0;
while (num!=0){
int temp=num%10;
result+=temp*temp;
num/=10;
}
return result;
}
}
总结:解题的关键在于题目中的”无限循环“,所以set集合还可以用来判断元素是否出现过。相同情况如果用数组或列表则需要从头遍历到尾,要熟练掌握不同数据结构地特点,发挥其最大长处。
6. 两数之和:
思想:定义map存储元素的值和对应下标。遍历数组元素,判断当前数和target之间的差值。如果差值存在map中,则返回当前下标和差值对应的value;如果差值不存在,则将当前遍历元素和下标放入map中。
方法:
class Solution {
public int[] twoSum(int[] nums, int target) {
// map中的key不会重复,value是数组下标
HashMap<Integer,Integer> map=new HashMap<>();
int[] result=new int[2];
for (int i=0;i<nums.length;i++){
int other=target-nums[i];
if (map.containsKey(other)){ // 另一个数存在
result[0]=i;
result[1]=map.get(other);
}else{ // 另一个数不存在
map.put(nums[i],i);
}
}
return result;
}
}
总结:map存储了数组元素和对应的下标值,同时map的键不能重复,也满足题目要求。