今日前置知识
哈希表理论基础
今日主要题目
主要学习网址
做题思路与具体代码
题目一:242.有效的字母异位词
做题思路
(hash数组经典题)
本题采用hash数组来实现哈希表的作用的知识,核心点是为了找到两个字符串之间的交集重复元素
首先初始化一个数组,然后将第一个字符串每个字符映射成数组每个位置上的值++
再将第二个字符串每个字符映射成数组每个位置上的值--
因为标题中有写两个字符串每个字符出现的次数都相同
所以可以采用一加一减的方法
再判断数组里面要是全为0,就说明两个字符串包含的字符都是一样的
具体代码
class Solution {
public boolean isAnagram(String s, String t) {
//本题采用数组来实现哈希表的作用
//统计字符串每个字母都放到数组上
//初始化哈希数组
int hash[]=new int[26];
//统计s上的字母数++
for(int i=0;i<s.length();i++){
hash[s.charAt(i)-'a']++;
}
//统计t上的字母数--
for(int i=0;i<t.length();i++){
hash[t.charAt(i)-'a']--;
}
//判断hash数组上有没有不为0的数,有的话就返回false
for(int count:hash){
if(count!=0)return false;
}
//是字母异位词
return true;
}
}
题目二:349. 两个数组的交集
本题采用hashset或hash数组的方法都可以,因为用hashset的情况是因为值太大,数组不能取那么大的范围
做题思路一:hashset方法
初始化两个hashset分别为set1和set2,把第一个数组的值放进去set1,然后遍历第二个数组,逐一与set1中的值比较,如果既存在于set1又存在于第二个数组,就放入set2
为什么要放入set2,因为我们可能会得到多个同样的结果,放入set2可以去重
最后再用数组存储set2中的元素
具体代码
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
//思路一:用set,范围太大用hashset
//初始化两个hashset,一个用来暂时存储,一个用来存并集(内部元素不重复,hashset特性)
Set<Integer> set1=new HashSet<>();
Set<Integer> set2=new HashSet<>();
//遍历数组一将nums1的值放入set1
for(int i:nums1){
set1.add(i);
}
//遍历数组二判断数组二的值是否在set1中
for(int i:nums2){
//如果存在,放入set2中
if(set1.contains(i)){
set2.add(i);
}
}
//将set2中的并集拿出来,放到数组中
//初始化数组
int result[]=new int[set2.size()];
int n=0;
for(int i:set2){
result[n++]=i;
}
return result;
}
}
做题思路二:hash数组方法
本题跟第一题不一样,没有说两个字符串每个字符出现的次数都相同
所以不能用一加一减的方式
分别用两个数组去存,分别都加,也就是将每个元素所对应的数组位上的数值++
然后初始化一个arraylist
同时遍历两个数组,如果在两个相同下标位置的数值都不为0,也就是两个原数组都包含该数,那么就将这个数存入arraylist
最后再将arraylist中的值存入数组中
(为什么这里要用到arraylist,因为我们放入并集的元素的个数是不确定的,而arraylist是动态数组,可以不用考虑初始容量的问题,这里要特别注意)
具体代码
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
//思路二:采用hash数组方法,因为里面数组的范围不是很大,才1000,如果是上万最好用hashset
//这道题定义两个计算数组存放两个数组出现数的个数
//然后用list存放两个计算数组的值
int hash1[]=new int[1001];
int hash2[]=new int[1001];
for(int i:nums1){
hash1[i]++;
}
for(int i:nums2){
hash2[i]++;
}
//初始化一个list
List<Integer> list=new ArrayList<>();
int a=0;
while(a<1001){
if(hash1[a]!=0&&hash2[a]!=0){
list.add(a);
}
a++;
}
//初始化返回数组
int result[]=new int[list.size()];
int n=0;
for(int i:list){
result[n++]=i;
}
return result;
}
}
题目三:202.快乐数
做题思路
本题也采用HashSet思路
这个数在逐渐求平方和的时候,可能会出现无限循环的情况,所以我们用hashset来存储过程中出现的结果,直到结果为1或者是出现了之前出现过的数(无限循环),再判断最后的值是否与1相等,相等证明是快乐数,不相等证明不是
(我们要存的一直都是平方和的数,就是一直存储平方和,直到它变成1或者和之前一样了)
具体代码
class Solution {
public boolean isHappy(int n) {
//本题采用hashset的方式来解决无限循环的问题,如果遇到变成和之前一样的元素就立刻返回false
//初始化hashset
Set<Integer> set1=new HashSet<>();
//如果元素变为1就退出或者是遇到变成和之前一样的元素就退出
while(n!=1&&!set1.contains(n)){
//先把数放入set1中
set1.add(n);
//改变数为他每个数位的平方
int result=0;
while(n>0){
//记住这里是想加
result+=(n%10)*(n%10);
n/=10;
}
//n变为result
n=result;
}
//如果结果为1,就返回true,结果不为1,就返回false
return n==1;
}
}
题目四:1. 两数之和
做题思路
本题采用HashMap的解法思路,本质还是哈希表,重复元素这类知识
我们遍历整个数组,每次遍历到这个元素,就判断距离目标值还需要哪个值,如果这个值正好在map中,就返回这个值的下标和当前元素的下标
如果没有找到,就存储该元素的值为key(方便别人寻找),索引为value(找到的时候返回值要用到),记得这个值一定要存储为key,这样才能寻找得到,没有找到就记得把自身存进map
(为什么用map,我们既要存储值又要存储索引,同时我们还可以找到之前遍历过的元素的值,且题目中说数组中同一个元素在答案里不能重复出现,也就是值可以作为map的key,用指针去寻找太麻烦)
(找之前遍历过的元素,重复元素去重,就考虑哈希表法:hash数组,hashset,hashmap三种方法供选择)
具体代码
class Solution {
public int[] twoSum(int[] nums, int target) {
//思路:用hashmap解决,map用来存放我们遍历过的元素
//初始化一个Map
Map<Integer,Integer> map1=new HashMap<>();
//遍历数组,每次存入数值
for(int i=0;i<nums.length;i++){
//达到目标值需要的值
int result=target-nums[i];
//如果在集合中,就将结果存入map集合中,然后返回
if(map1.containsKey(result)){
//返回顺序无所谓,我就随便返回了
return new int[]{map1.get(result),i};
}
map1.put(nums[i],i);
}
return new int[]{};
}
}