代码随想录Day6 | 242.有效的字母异位词 |349. 两个数组的交集 | 202. 快乐数 | 1. 两数之和
242.有效的字母异位词
题目: 给定两个字符串 s
和 t
,编写一个函数来判断t
是否是s
的字母异位词。
*注意:*若 s
和 t
中每个字符出现的次数都相同,则称 s
和 t
互为字母异位词。
思路: 统计两个字符串中字母的出现的频率,如果频率相同那么为字母异位词。可以使用一个哈希表来统计词频,但是我们注意字母只有26个,我们可以使用一个长度为26的数组来统计,初始化数组为0,首先遍历s,在对应的字母的位置+1,然后遍历t在字母对应的位置-1,最后如果该数组所有位置均为0,那么s和t则为字母异位词。
代码:
class Solution {
public boolean isAnagram(String s, String t) {
int[] fre = new int[26];
for(int i = 0; i < s.length(); i++){
fre[s.charAt(i) - 'a']++;
}
for(int i = 0; i < t.length(); i++){
fre[t.charAt(i) - 'a']--;
}
for(int i = 0; i < fre.length; i++){
if(fre[i] != 0 ) return false;
}
return true;
}
}
时间复杂度:O(n),空间复杂度O(n)
349. 两个数组的交集
题目: 给定两个数组 nums1
和 nums2
,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。
思路: 暴力解法:两个for循环,记录重复的元素,时间复杂度O(n**2)。哈希表:使用两个哈希表,先循环遍历其中一个数组,将所有元素添加到哈希表中,然后遍历第二个数组,只有第一个哈希表中含有的元素才会存入到第二个哈希表中。
代码:
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
HashSet<Integer> set1 = new HashSet<>();
HashSet<Integer> set2 = new HashSet<>();
for(Integer num : nums1){
set1.add(num);
}
for(Integer num : nums2){
if(set1.contains(num)){
set2.add(num);
}
}
//将set转化成数组
return set2.stream().mapToInt(x -> x).toArray();
}
}
时间复杂度:O(n),空间复杂度O(n)
202. 快乐数
题目: 编写一个算法来判断一个数 n 是不是快乐数。
「快乐数」 定义为:
对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
如果这个过程 结果为 1,那么这个数就是快乐数。
如果 n 是 快乐数 就返回 true ;不是,则返回 false 。
思路: 快乐数的判断的一个关键是如果每一轮计算出来的值有重复的,那么这个计算就会陷入死循环,就一定不是快乐数,那么我们的判断就很简单了,将每一轮的计算结果放入一个set中,如果计算出重复的值返回false,否则就一直计算,直到计算结果为1或者计算结果重复。
代码:
每次都进行数据类型转换,效率较低。
class Solution {
public boolean isHappy(int n) {
Set<Integer> set = new HashSet<>();
set.add(n);
while(true){
int sum = 0;
for(char num : (n + "").toCharArray()){
sum += Math.pow(Integer.parseInt(num + ""), 2);
}
if(sum == 1) return true;
if(!set.contains(sum)) set.add(sum);
else return false;
n = sum;
}
}
}
对10取余,可以得到最后一个数的值。
class Solution {
public boolean isHappy(int n) {
Set<Integer> set = new HashSet<>();
set.add(n);
while(true){
int sum = 0;
while(n > 0){
sum += Math.pow(n % 10, 2);
n = n / 10;
}
if(sum == 1) return true;
if(!set.contains(sum)) set.add(sum);
else return false;
n = sum;
}
}
}
因为轮次不确定,因此无法计算时间复杂度和空间复杂度
1. 两数之和
题目: 给定一个整数数组 nums
和一个整数目标值 target
,请你在该数组中找出 和为目标值target
的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
思路: 这道题用set的话会非常麻烦,因为返回值是索引值而不是数值,采用set的话还要遍历获取索引。采用map的方法,key存放num[i],value存放i,可以直接获取到索引值。遇到一个值,先判断此时map里面有没有和该值相加为target的值,如果有,则返回这两个值的索引,没有,则将该值和其索引放入到map中。
代码:
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] res = new int[2];
Map<Integer, Integer> map = new HashMap<>();
for(int i = 0; i < nums.length; i++){
int tmp = target - nums[i];
if(map.containsKey(tmp)){
res[0] = i;
res[1] = map.get(tmp);
return res;
}
map.put(nums[i], i);
}
return res;
}
}
时间复杂度:O(n),空间复杂度O(n)