代码随想录算法训练营第六天 |哈希表理论基础,242.有效的字母异位词,349.两个数组的交集,202. 快乐数,1. 两数之和
242.有效的字母异位词
给定两个字符串 s
和 t
,编写一个函数来判断 t
是否是 s
的
字母异位词
示例 1:
输入: s = "anagram", t = "nagaram"
输出: true
示例 2:
输入: s = "rat", t = "car"
输出: false
提示:
1 <= s.length, t.length <= 5 * 104
s
和t
仅包含小写字母
进阶: 如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况?
思想:
- 由于英文单词只有26个字母,所以可以声明一个具有26个元素的数组用来存储每个字母在第一个单词中出现的次数。然后再用记录次数的数组减去在第二个字符串相同字母出现的次数。看是否数组中的元素为零,如果是0则是有效的字母异位。
- 在这里不需要知道每个字母具体的ASCII码的值,因为在俩个字母相减的时候,会自动转换为ASCII码相减,比如a-a=0,b-a=1。
class Solution {
public boolean isAnagram(String s, String t) {
int[] count = new int[26];
if(s.length() != t.length()){
return false;
}
for(int i = 0;i < s.length();i++){
count[s.charAt(i)-'a']++;
}
for(int i = 0;i < t.length();i++){
count[t.charAt(i)-'a']--;
}
for(int i = 0;i < s.length();i++){
if(count[s.charAt(i)-'a'] != 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] 也是可通过的
提示:
1 <= nums1.length, nums2.length <= 1000
0 <= nums1[i], nums2[i] <= 1000
思想1:使用HashSet求解,会自动帮我们把重复的元素去掉。将第一个数组存放在哈希表中,然后查看第二个数组中是否有元素在哈希表中出现,如果出现就加入到存储交集的哈希表中。
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
if(nums1 == null || nums1.length == 0 || nums2 == null || nums2.length == 0){
return new int[0];
}
Set<Integer> hashSet = new HashSet<>();
Set<Integer> resSet = new HashSet<>();
for(int num : nums1){
hashSet.add(num);
}
for(int num : nums2){
if(hashSet.contains(num)){
resSet.add(num);
}
}
int[] nums = new int[resSet.size()];
int i = 0;
for(int num : resSet){
nums[i++] = num;
}
return nums;
}
}
思想2:由于题目更新,数组大小和数量有限,所以可以使用数组求解。比如说:数组中有1000就用nums1[1000]存储其出现的次数,只要nums1[1000]和nums2[1000]都大于零,那么就是交集,就把他加到新的数组中,如何添加呢?直接把元素值不为零的下标加入即可。
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
int[] has1 = new int[1001];
int[] has2 = new int[1001];
for(int i : nums1){
has1[i]++;
}
for(int i : nums2){
has2[i]++;
}
List<Integer> resList = new ArrayList<>();
for(int i = 0;i < 1001;i++){
if(has1[i] > 0 && has2[i] > 0){
resList.add(i);
}
}
//转换为数组
int[] nums = new int[resList.size()];
int i = 0;
for(int num : resList){
nums[i++] = num;
}
return nums;
}
}
注意:声明数组时,一定要写中括号[].
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
思想:注意一点,根据快乐数的计算规则,在计算过程中,如果他不是快乐数,那么一定会出现重复的数字。那么如果出现了重复的数字我们就能判断他不是快乐数。因为,你再次出现了,表示后续的数字序列会重复出现。
注意:一次只判断一个数字。
class Solution {
public boolean isHappy(int n) {
Set<Integer> has = new HashSet<>();
while(n != 1 && !has.contains(n)){
has.add(n);
int s = 0;
while(n > 0){
int temp = n % 10;
s += temp * temp;
n = n/10;
}
n = s;
}
return n == 1;
}
}
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]
思想:
- 也就是俩俩元素组合求和,看能不能找到目标值。只要我加过了就不用再相加了,那我就每次多一个数,多的一个数肯定没有和之前遍历过的元素相加过。
- 这里因为我们要寻找自己的目标值(假如1+2=3,已知1,那么2就是目标值)是否存在,又要记录其下标,所以用map比较合适。
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);
break;
}else{
map.put(nums[i],i);
}
}
return res;
}
}