**代码随想录算法训练营第六天 | 哈希表理论基础 | 242.有效的字母异位词| 349. 两个数组的交集 |202. 快乐数 |1. 两数之和 **
242.有效的字母异位词
代码
/**
* 242. 有效的字母异位词 字典解法
* 时间复杂度O(m+n) 空间复杂度O(1)
*/
class Solution {
public boolean isAnagram(String s, String t) {
int[] record = new int[26];
for (int i = 0; i < s.length(); i++) {
record[s.charAt(i) - 'a']++; // 并不需要记住字符a的ASCII,只要求出一个相对数值就可以了
}
for (int i = 0; i < t.length(); i++) {
record[t.charAt(i) - 'a']--;
}
for (int count: record) {
if (count != 0) { // record数组如果有的元素不为零0,说明字符串s和t 一定是谁多了字符或者谁少了字符。
return false;
}
}
return true; // record数组所有元素都为零0,说明字符串s和t是字母异位词
}
}
题图
心得
- 需要把字符映射到数组也就是哈希表的索引下标上,因为字符a到字符z的ASCII是26个连续的数值,所以字符a映射为下标0,相应的字符z映射为下标25。
- 再遍历 字符串s的时候,只需要将 s[i] - ‘a’ 所在的元素做+1 操作即可,并不需要记住字符a的ASCII,只要求出一个相对数值就可以了。 这样就将字符串s中字符出现的次数,统计出来了
- 26个英文字母
帖子
-
[java用for循环输出数组,Java打印输出数组的三种方式:传统的for循环方式,for each循环,利用Arrays类中的toString方法…_编剧学徒的博客-CSDN博客](https://blog.csdn.net/weixin_42518930/article/details/115735240?ops_request_misc=&request_id=&biz_id=102&utm_term=java for(inta:b)&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-1-115735240.142v68control,201v4add_ask,213v2t3_esquery_v1&spm=1018.2226.3001.4187)
-
Java中length、length()、size()区别_Techyu的博客-CSDN博客_nums.length()
-
-
这里的return 应该在大的方法(public)里面
-
record[s.charAt(i) - 'a']++; // 并不需要记住字符a的ASCII,只要求出一个相对数值就可以了 //record[s.charAt(i)]++;
349. 两个数组的交集
代码
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> set1 = new HashSet<>();
Set<Integer> resSet = new HashSet<>();
//遍历数组1
for (int i : nums1) {
set1.add(i);
}
//遍历数组2的过程中判断哈希表中是否存在该元素
for (int i : nums2) {
if (set1.contains(i)) {
resSet.add(i);
}
}
//将结果几何转为数组
return resSet.stream().mapToInt(x -> x).toArray();
}
}
心得
-
请问判断数组为空,为什么nums = null和nums.length() == 0都要写,不是等效的吗?
-
int[] array = null; 数组为空,此时array不指向任何对象;
int[] array = new int[0]; 定义一个长度为0的数组;
-
如果写成这样 if(array.length == 0 || array == null)在array == null 为true 的情况下就会报空指针异常(运行时异常)
题图
心得
-
结果几何转为数组:
-
return resSet.stream().mapToInt(x -> x).toArray();
-
nums应该和null挂钩
-
if (nums1 == null || nums1.length == 0 //if(nums1==0|| nums1.length==0)
202. 快乐数
代码
class Solution {
public boolean isHappy(int n) {
Set<Integer> record = new HashSet<>();
while (n != 1 && !record.contains(n)) {
//n如果是1,则跳出循环,n如果是重复的,也跳出while(说明这道题是无限循环)
record.add(n);
n = getNextNumber(n);
}
return n == 1;
//如果是1,返回true,如果是无限循环的数,则返回false
}
private int getNextNumber(int n) {
int res = 0;
while (n > 0) {
int temp = n % 10;
//获取个位数
res += temp * temp;
n = n / 10; //获取十位数及其以上的数字
}
return res;
}
}
题图
![image-20221212131154712](https://gaopunike-test-srt.oss-cn-beijing.aliyuncs.com/img/image-20221212131154712.png)
心得
-
题目中说了会 无限循环,那么也就是说求和的过程中,sum会重复出现,这对解题很重要!
-
所以这道题目使用哈希法,来判断这个sum是否重复出现,如果重复了就是return false, 否则一直找到sum为1为止。
-
-
有没有返回值也得看力扣的官方有没有给你自定义函数时候有返回值
-
int temp = n % 10; //获取个位数
-
n = n / 10; //获取十位数及其以上的数字
-
return n == 1; 因为返回值上面定义是boolean所以这个是True\false
-
if(TRUE||false) 里面只能是布尔表达式,所以用到==和!=
-
-
while(布尔表达式) 也是和if一样
-
while (n != 1 && !record.contains(n)) {
//n如果是1,则跳出循环,n如果是重复的,也跳出while(说明这道题是无限循环) -
return n == 1;
//如果是1,返回true,如果是无限循环的数,则返回false -
java里面的自定义方法在solution中,并列于public,而且要把参数类型都写出来
-
private int getNextNumbers(int n) //private int getNextNumbers(n)
-
-
自己定义的有返回值,那么就应该写return
-
为什么这么定义不可以呢?
-
res += temp*temp; //必须在上面定义int res =0; //不能省略成为int res = temp*temp;
帖子
- [java if语句_HE627386528的博客-CSDN博客_ja if语句](https://blog.csdn.net/HE627386528/article/details/123852065?ops_request_misc=%7B%22request%5Fid%22%3A%22167082110416800182734048%22%2C%22scm%22%3A%2220140713.130102334…%22%7D&request_id=167082110416800182734048&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2alltop_click~default-2-123852065-null-null.142v68control,201v4add_ask,213v2t3_esquery_v1&utm_term=java if&spm=1018.2226.3001.4187)
- [Java中的!=和==_^菜的博客-CSDN博客_java中!](https://blog.csdn.net/potato_me/article/details/113503588?ops_request_misc=&request_id=&biz_id=102&utm_term=java !&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-1-113503588.142v68control,201v4add_ask,213v2t3_esquery_v1&spm=1018.2226.3001.4187)
- [java while语句_Java while循环语句_泡泡SOHO的博客-CSDN博客](https://blog.csdn.net/weixin_35834213/article/details/114053302?ops_request_misc=&request_id=&biz_id=102&utm_term=java while&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-7-114053302.142v68control,201v4add_ask,213v2t3_esquery_v1&spm=1018.2226.3001.4187)
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++){
int temp = target - nums[i]; // 遍历当前元素,并在map中寻找是否有匹配的key
if(map.containsKey(temp)){
res[1] = i;
res[0] = map.get(temp);
break;
}
map.put(nums[i], i); // 如果没找到匹配对,就把访问过的元素和下标加入到map中
}
return res;
}
题图
心得
-
什么时候使用哈希法,当我们需要查询一个元素是否出现过,或者一个元素是否在集合里的时候,就要第一时间想到哈希法
-
我们不仅要知道元素有没有遍历过,还有知道这个元素对应的下标,需要使用 key value结构来存放,key来存元素,value来存下标,那么使用map正合适。
-
使用数组和set来做哈希法的局限。
- 数组的大小是受限制的,而且如果元素很少,而哈希值太大会造成内存空间的浪费。
- set是一个集合,里面放的元素只能是一个key,而两数之和这道题目,不仅要判断y是否存在而且还要记录y的下标位置,因为要返回x 和 y的下标。所以set 也不能用
-
这道题目中并不需要key有序,选择std::unordered_map 效率更高!(在Java中就对应着HashMap和TreeMap)
-
这个0和1的顺序也有讲就,如果是升序的数组,那么res[0]应该是先存入map里面的
-
res[0]=map.get(temp); res[1]=i;
-
if(nums == null || nums.length == 0){ return res; } //忘记考虑边界条件,没有健壮性
-
找到这两个数,有了这个数组,那么就可以直接跳出了,(不然还会一直进行for循环)