代码随想录算法训练营day06 | 242. 有效的字母异位词, 349. 两个数组的交集, 202. 快乐数, 1. 两数之和
java哈希结构总结:
https://www.runoob.com/java/java-collections.html
https://blog.csdn.net/qq_34332616/article/details/114692538
哈希表理论基础
242. 有效的字母异位词
解法一:数组统计
public boolean isAnagram(String s, String t) {
//长度不相等必定不是
if(s.length()!=t.length()){
return false;
}
int[] num = new int[26];
char[] charArr1 = s.toCharArray();
for(int i=0;i<s.length();i++){
num[charArr1[i]-'a'] +=1;
}
// System.out.println(num);
char[] charArr2 = t.toCharArray();
for(int i=0;i<t.length();i++){
num[charArr2[i]-'a'] -=1;
}
for(int i=0;i<num.length;i++){
if(num[i]!=0){
return false;
}
}
return true;
}
349. 两个数组的交集
解法一:HashSet
使用HashSet时记得指定泛型, 否则得到的Set内元素是Object, 后续转为数组会出错.
public int[] intersection(int[] nums1, int[] nums2) {
HashSet<Integer> records = new HashSet<>();
HashSet<Integer> result = new HashSet<>();
// 去重复并存入records
for(int i=0;i<nums1.length;i++){
records.add(nums1[i]);
}
//查找重复值存入result集合
for(int i=0;i<nums2.length;i++){
if(records.contains(nums2[i])){
result.add(nums2[i]);
}
}
//方法1:将结果集合转为数组
//return result.stream().mapToInt(x -> x).toArray();
//方法2:另外申请一个数组存放result中的元素,最后返回数组
int[] arr = new int[result.size()];
int j = 0;
for(int i : result){
arr[j++] = i;
}
return arr;
}
解法二:数组记录
力扣给的范围是: 0 <= nums1[i], nums2[i] <= 1000
因此可以使用数组记录字符位置
public int[] intersection(int[] nums1, int[] nums2) {
int[] records = new int[1001];
for(int num: nums1){
records[num] = 1;
}
HashSet<Integer> res = new HashSet<>();
for(int num : nums2){
if(records[num]==1){
res.add(num);
}
}
int[] result = new int[res.size()];
int j = 0;
for(int i : res){
result[j++] = i;
}
return result;
}
202. 快乐数
教程:https://programmercarl.com/0202.%E5%BF%AB%E4%B9%90%E6%95%B0.html
解法一:优
public boolean isHappy(int n) {
HashSet<Integer> record = new HashSet<>();
while(!record.contains(n)){
record.add(n);
n =getNextNumber(n);
if(n==1){return true;}
}
return false;
}
//计算返回n每个位置上的数字的平方和
private int getNextNumber(int n) {
int sum = 0;
while (n > 0) {
int temp = n % 10;
sum += (n % 10) * (n % 10);
n = n / 10;
}
return sum;
}
解法二:没单独写出函数
public boolean isHappy(int n) {
HashSet<Integer> records = new HashSet<>();
records.add(n);
int sum = 0 ;
while(!records.contains(sum)){
// 将上一次循环数得到的存入集合中
records.add(sum);
//得到下一个数存到sum
sum=0;
while(n!=0){
sum+=(n%10)*(n%10);
n = n/10;
}
//如果得到1,满足要求返回true
if(sum==1){
return true;
}
//否则将n改为下个数
n=sum;
}
return false;
}
1. 两数之和
教程视频:https://www.bilibili.com/video/BV1aT41177mK/?spm_id_from=333.788&vd_source=ddffd51aa532d23e6feac69924e20891
进阶:你可以想出一个时间复杂度小于 O(n2) 的算法吗?
解法一:HashMap记录已经遍历过的数值和索引
public int[] twoSum(int[] nums, int target) {
HashMap<Integer, Integer> record = new HashMap<>();
for(int i=0;i<nums.length;i++){
if(record.containsKey(target-nums[i])){
return new int[]{record.get(target-nums[i]),i};
}
record.put(nums[i],i);
}
return new int[2];
}
解法二:暴力破解,双重for循环
时间复杂度高,暂不实现.
总结
1.当需要快速寻找之前遍历过的内容,使用哈希结构.
2.数组适用于有限内容的查找; HashSet适用于去重复查找; HashMap适合带键值对的查找.
3.使用HashSet和HashMap时记得指定泛型, 否则得到的集合内元素是Object.