代码随想录算法训练营第六天|242.有效字母的异位词、349.两个数组的交集、202快乐数、1.两数之和
哈希表的应用:当哟啊快速判断每个元素是否在集合中时需要用到哈希表。哈希表的数据结构有三种:数组(用于数据量小)、set()、map(需要key和value对应)。
242.有效字母的异位词
给定两个字符串 *s*
和 *t*
,编写一个函数来判断 *t*
是否是 *s*
的字母异位词。
**注意:**若 *s*
和 *t*
中每个字符出现的次数都相同,则称 *s*
和 *t*
互为字母异位词。
示例 1:
输入: s = "anagram", t = "nagaram"
输出: true
示例 2:
输入: s = "rat", t = "car"
输出: false
提示:
1 <= s.length, t.length <= 5 * 104
s
和t
仅包含小写字母
题解:这道题是数组在哈希表中的典型应用。
因为只有26个小写字母,而且这26个元素是连续的,所以采用数组这种数据结构。将字符串的字母减去字母a得到的就是从0到25这26个字母的下标索引。数组的值就是元素出现的次数,也就是遍历到这个元素,对应的数组值就加一。这样就记录了字符串中每个元素出现的次数。再遍历第二个字符串,让数组值减减,最后判断数组值是否全为0,就可以了。
代码:
class Solution {
public boolean isAnagram(String s, String t) {
int [] arr=new int[26];
for(int i=0;i<s.length();i++){
arr[s.charAt(i)-'a']++;
}
for(int i=0;i<t.length();i++){
arr[t.charAt(i)-'a']--;
}
for(int i=0;i<arr.length;i++){
if(arr[i]!=0){
return false;
}
}
return true;
}
}
349.两个数组的交集
给定两个数组 nums1
和 nums2
,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。
示例 1:
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]
示例 2:
输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[9,4]
解释:[4,9] 也是可通过的
题解:一定要记得set 的应用。包括获取set的大小(set.size()),set添加元素的方法(set.add),判断一个元素是否在set中的方法(set.contains(x))。需要注意的是,set有toArray()的方法,但是转换成数组的元素类型是object,所以还是建议重新创建一个数组来存放set的值。
至于这个题,就是将第一个数组放到set中,然后看第二个数组的值有没有在里面出现,出现的话就记录。
代码:
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
Set<Integer> haset=new HashSet<Integer>();
Set<Integer> resset=new HashSet<Integer>();
for(int n:nums1){
haset.add(n);
}
for(int n:nums2){
if(haset.contains(n)){
resset.add(n);
}
}
int [] res=new int[resset.size()];
int i=0;
for(int x:resset){
res[i++]=x;
}
return res;
}
}
202.快乐数
编写一个算法来判断一个数 n
是不是快乐数。
「快乐数」 定义为:
- 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
- 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
- 如果这个过程 结果为 1,那么这个数就是快乐数。
如果 n
是 快乐数 就返回 true
;不是,则返回 false
。
示例 1:
输入:n = 19
输出:true
解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1
示例 2:
输入:n = 2
输出:false
题解:当不知道一个数是几位数时,求各个位上的平方和的方法要记住。就取这个数的个位(模),然后将这个数除以10,再求个位,while循环,判断的条件是这个数大于0。接下来就是正题了,while循环,因为这个数可能会一直循环下去,所以当set中已经包含这个值时,就要退出循环,不然它就会一直循环,最后超出时间限制,退出循环需要两个条件。
代码:
class Solution {
public boolean isHappy(int n) {
Set<Integer> set1=new HashSet<>();
while(n!=1 && !set1.contains(n)){
set1.add(n);
n=getNum(n);
}
return n==1;
}
private int getNum(int n){
int sum=0;
while(n>0){
int temp=n%10;
sum+=temp*temp;
n=n/10;
}
return sum;
}
}
1、两数之和
给定一个整数数组 nums
和一个整数目标值 target
,请你在该数组中找出 和为目标值 target
的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:
输入:nums = [3,2,4], target = 6
输出:[1,2]
示例 3:
输入:nums = [3,3], target = 6
输出:[0,1]
题解:
-
什么时候使用哈希表
当需要判断一个元素是否出现过,或是否出现在集合里。
-
为什么用哈希表
本题需要一个集合来存放我们遍历过的元素,然后遍历数组时去询问这个集合,看target-数组当前值 是否在集合里,在就找到了答案,不在就将这个值和它的下标放到map里面
-
本题map用来存什么
用来存已经遍历过的数组元素的值和它的下标
- map中的key 和 value 是用来存什么的
key:数组的值; value : 数组下标;
- 往 map 里面添加值:put(); 集合是:add()。
map 是在最短的时间内查找 key是否在map里面出现过。 因为我们找的是元素是否出现过,所以将数组的值作为key,下标作为value
根据key得到value值 :value=map.get(key)
详细说明:本题可以理解为找到最近的两个数的和等于target就可以退出了。返回的是含两个元素的数组,所以先创建一个大小为2的数组。然后判断这个数组是否为空或者长度是否为零。接下来,创建一个map,这个map的key用来保存nums的数组值,value来保存下标(因为最后返回的是数组的下标,所以可以通过map.get(key)的方式得到)。接下来就是遍历数组,然后将遍历的数组值和下标保存在map集合中,之后再判断它需要的那个值有没有在map 中出现过。map的key值有没有出现过的判断方法: map.containsKey()。
代码:
class Solution {
public int[] twoSum(int[] nums, int target) {
int [] res=new int[2];
if(nums==null || nums.length==0){
return res;
}
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]=i;
res[1]=map.get(temp);
}
map.put(nums[i],i);
}
return res;
}
}