- 写在前面,今天的打卡题目是我一刷,加上自己还没有学完java中的set和map接口,所以读完题目已经很吃力,这也说明 我必须加快java的学习,打好语言基础。
- 另一方面,我想大声表扬自己的进步地方:在我研一下学期用c++的时候,遇到了同样的情况,也刷到了“哈希表”这一章节,当时也是没有学到c++的set和map,但是我直接跳过了哈希表和栈这两个章节,现在我参加了训练营之后,很希望每天跟上打卡进度,以及一位群友说:哪里不会学哪里,我就去简单看了一下set 类,能理解答案的代码了。
目录
哈希表理论基础
之前考研的时候,学过哈希表,当时没有学会,现在也还是有点懵,所以我目前还是停留在了解的阶段,总结不出来什么很好的知识点。(-_-||) 有待补充
242 有效的字母异位词
题目链接
242. 有效的字母异位词 - 力扣(LeetCode)
题目要求
给定两个字符串 s和t,编写一个函数来判断 t 是否是 s 的字母异位词。注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。
思路分析
学透哈希表,数组使用有技巧!Leetcode:242.有效的字母异位词_哔哩哔哩_bilibili ,这道题目我今天2022年9月26日第一次刷的时候,是看了卡哥的视频讲解。所以推荐和我一样一刷迷茫的朋友先看一遍视频,再自己总结。
- 是判断两个字符串中的每一个字符出现的次数是否相同,所以可以创建一个长度为26的数组(最多有26个字母)
int [] record=new int[26];
- 将字符串s转为char [ ] ,然后遍历char[] ,将每一个出现的字符次数累加到对应数组的位置。
char[] chars=s.toCharArray(); for(int i=0;i<chars.length;i++){ record[char[i]-'a']++; } // char[i]-'a': 这个值映射到record对应的下标
- 同样的,将字符串t 转为char[],然后遍历char[] ,但是不同的是,这次record[] 的对应位置要进行--操作
- 最后如果record[]中元素全部是0,则说明两个字符串中每个字符出现的字符次数是相同的
完整代码如下
本题收获
- 克服了一部分的“畏难心理”,看到不熟悉的知识没有退缩,看完思路和答案之后,自己能够独立的写出来。
- 在写这道题目的时候,忘记了字符相减之后的结果是哪个类型?然后动手试了一下,发现输出的是int 类型,自己比之前有动手尝试的意识,点赞。
349 两个数组的交集
题目链接
349. 两个数组的交集 - 力扣(LeetCode)
题目要求
给定两个数组 nums1
和 nums2
,返回它们的交集 。输出结果中的每个元素一定是唯一 的。我们可以不考虑输出结果的顺序 。
思路分析
- 题目中说:不考虑输出结果的顺序,很符合set接口的特点
- Set集合是由一串无序的,不能重复的相同类型元素构成的集合
- 所以这个题目可以用set接口中的方法来做,把数组转为set,一方面已经去除了数组中重复的元素
- 利用set类中的方法来实现对第一个数组的去重,让再去判断第二个数组中的元素是否在集合中,最后把交集转为数组输出。
完整代码
本题收获
- 简单了解了set类的特性:无序存放非重复的元素,但是输出是有序的(简单看了一点韩顺平老师的java视频)
- 现在编程语言已经阻碍了我学数据结构的进度,自己学java的速度要加快些。
202 快乐数
题目链接
题目要求
编写一个算法: 判断一个数 n 是不是快乐数。
「快乐数」 定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
然后重复这个过程直到这个数变为 1,也可能是无限循环 但始终变不到 1。如果这个过程 结果为 1,那么这个数就是快乐数。如果 n 是 快乐数 就返回 true ;不是,则返回 false 。
思路分析
- (反思),这个题目自己有点太轻易的看答案了,没有好好体会一下“无限循环”的意思。
- 关于无限循环的解读: 一旦出现无限循环,就可以判定这个数不是:“快乐数”。所以结合set 集合,保存不重复的元素,一旦集合中出现重复元素,可以判定不是快乐数。
- 要重点关注:如何实现这个数的更新,每一次将该数替换为它每个位置上的数字的平方和,一定是从个位开始计算,先求余,再除以10.
-
while(n!=1&& !(set.contains(n))) // 我最早写的是 while(n!=1 ||!(set.contains(n))) // 这个是很不严谨,这样一旦进入循环的话,当n!=1 ,无法跳出,就会超时。
代码如下
import java.util.HashSet;
//leetcode submit region begin(Prohibit modification and deletion)
class Solution {
public boolean isHappy(int n) {
Set<Integer> set = new HashSet<>();
while(n!=1&& !(set.contains(n))){
// 将n 添加到集合set中
set.add(n);
// 更新n 的值
n=UpDate(n);
}
// if(n==1)
// {
// return true;
// }
// else {
// return false;
// }
return n==1;
}
public static int UpDate (int n)
{
int res=0;
while (n!=0){
res += (n%10)*(n%10);
// System.out.println(res);
n=n/10;
}
return res;
}
}
本题收获
- 反思自己今天的思考不到位,读完题目之后,很快地看了解析,下次要注意,至少先认真读题,是第一次刷这个题,but 不设限。第一次不死磕题目,不等于直接看题解。
- 好一点的是:简单看完题解之后,很好的理解了思路,重点关注“无限循环”,一旦可以判断进入了无限循环,就能够判定不是快乐数。
- 细节:while() 循环条件,第一次自己没有琢磨透。|| 前者是true的时候,就不再判断第二个条件。
1 两数之和
题目链接
题目要求
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出和为目标值 target的那两个整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
思路分析
基本思路
- 先夸,简直是膜拜卡尔哥,以及写java答案的大佬,好绝啊
- 这个题目比较简单粗暴的一种思路是:嵌套的for循环,注意内层for循环变量从j=i+1开始,因为题目强调:数组中同一个元素在答案中不能重复出现。
进阶思路
参考了代码随想录的代码,自己写了注解,学到了。
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++){ // 两个数之和是9,当遍历到nums[i],可以直接查找target-nums[i]的值是否在map集合中 // 判断一个元素是否出现过?考虑使用哈希表或者哈希结构。 // 为什么是map类型呢?因为需要保存元素值和下标。 int temp = target - nums[i]; if(map.containsKey(temp)){ res[1] = i; // 满满的细节啊 res[0] = map.get(temp); } map.put(nums[i], i); } return res; }
本题收获
- 这个题目让自己接触到了新知识点“map”类,保存键值对(Key-value), Key必须是唯一存在的。
- “判断一个元素是否出现过?”→ 使用哈希表或者哈希结构。通过这个题目加深了这句话的理解,有时候可以更加灵活的考虑问题。
- 值得反复看,以及要加快自己的学习java的速度。