day5是周天,休息的。
day6来到哈希表。回顾下今天任务。今天代码基本都没写注释,因为随想录网站思路很明确了。
1.哈希表的理论基础
看到哈希就想一下哈希表的哈希码,哈希函数。要知道哈希函数的实现原理是什么,因为这个原理所以会产生什么情况。会产生哈希冲突,怎么解决。拉链法和线性探测法。两个是什么原理,看一眼要知道大概。哈希结构有几种,数组、set、map,其中set、map各有三种。三种都是什么分类?什么特点?都要熟悉一点。
注意哈希法的应用场景:
总结一下,当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法。
但是哈希法也是牺牲了空间换取了时间,因为我们要使用额外的数组,set或者是map来存放数据,才能实现快速的查找。
如果在做面试题目的时候遇到需要判断一个元素是否出现过的场景也应该第一时间想到哈希法!
2有效的字母异位词:代码随想录
力扣链接:. - 力扣(LeetCode)
搞清楚题意,这两货里面的字符次数相同知识位置不同,所以叫异位。
跟着随想录的思路走,其实这种的都可以用标志位解题,一旦标志位不全为1,则就说明有别的情况。
/*
* Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved.
*/
package TrainingCamp;
/**
* 有效的字母异位词
*
* https://leetcode.cn/problems/valid-anagram/
* 数组也是一张哈希表
*/
public class _6_1ValidAlphabeticWords {
public static boolean isAnagram(String s, String t) {
int[] res = new int[26];
for (int i = 0; i < s.length(); i++) {
res[s.charAt(i) - 'a'] += 1;
}
for (int i = 0; i < t.length(); i++) {
res[s.charAt(i) - 'a'] -= 1;
}
for (int s1 : res) {
if (s1 != 0) {
return false;
}
}
return true;
}
public static void main(String[] args) {
String s = "anagram";
String t = "nagaram";
System.out.println(isAnagram(s, t));
}
}
3.两个数组的交集:代码随想录
力扣链接:代码随想录
哈希表用来判断交集真的不要太爽,o(1)谁用谁知道。声明两个hashset,先随便加一个数组的所有元素到哈希set里,再contains判断一下,存在的才放到第二个hashset。最后流式输出,或者遍历下。
/*
* Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved.
*/
package TrainingCamp;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
/**
* 两个数组的交集
*
*
* https://leetcode.cn/problems/intersection-of-two-arrays/
*/
public class _6_3TwoArrayContains {
public static int[] intersection(int[] nums1, int[] nums2){
Set<Integer> set1 = new HashSet<>();
Set<Integer> set2 = new HashSet<>();
for (int i : nums1){
set1.add(i);
}
for (int i : nums2){
if (set1.contains(i)){
set2.add(i);
}
}
return set2.stream().mapToInt(x->x).toArray();
}
public static void main(String[] args) {
int[] nums1={4,9,5};
int[] nums2={9,4,9,8,4};
System.out.println(Arrays.toString(intersection(nums1,nums2)));
}
}
return set2.stream().mapToInt(x->x).toArray();
也可以换成
//方法2:另外申请一个数组存放setRes中的元素,最后返回数组
int[] arr = new int[resSet.size()];
int j = 0;
for(int i : resSet){
arr[j++] = i;
}
return arr;
4.快乐数:代码随想录
力扣链接:. - 力扣(LeetCode)
不要被名字吓到,看一下示例,就知道咋写了。
注意判断的条件,用while判断,定义一个hashset,用来判断有没有重复出现,不能死循环。
当n!=1并且集合里面不包含n时候才进入循环,不进入循环只有两种情况,n=1(本身) || n=0(快乐数);
代码忘记贴了,明天贴一下。
5.两数之和(梦开始的地方!):代码随想录
力扣链接:. - 力扣(LeetCode)
蛮有难度的题,反正第一次写确实不会,一点思路没有。这道题回味一下,再整理下思路。
得定义一个返回的数组,存储的符合条件的数组中两个数的下标,一定注意返回的是下标。
为什么用hashmap,因为当遍历到符合条件的值的时候,返回的是下标并不是值,所以还要去循环找下标吗,不用了,hashmap直接解决,key存数组的值,value存值对应的下标。
有个细节:注意i一直是res数组的第二个,即res[1]。因为只有之前有存进去的,到i这才能找到map里符合条件的,所以i一定大,得存第二位。这个一定要注意。
//使用哈希表
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;
}