1、哈希表理论基础
哈希表对应 Java 来说,就是 HashMap 、HashSet 最常见了,一般是由 key-value 的结构组成,可以通过传入 key 快速判断key 是否存在,时间复杂度可以做到O(1),
总结就是当我们遇到了要快速判断一个元素是否出现在集合里的时候,就要考虑哈希法了。
但是哈希法也是牺牲了空间换取时间,因为我们要使用额外的数组,set 或者是 map 来存放数组才能快速查找。
2、题目1:242-有效的字母异位词
给定两个字符串
s
和t
,编写一个函数来判断t
是否是s
的 字母异位词示例 1:
输入: s = "anagram", t = "nagaram" 输出: true
示例 2:
输入: s = "rat", t = "car" 输出: false
s
和t
仅包含小写字母
即,每个字母出现的次数都相等即为异位词。
思路:
-
通过一个map来记录值,另一个map来删除值,直到map中的各个位置的值为0,如果出现不为0的则代表不是异位词。
代码:
public boolean isAnagram(String s, String t) {
HashMap<Character, Integer> map = new HashMap<>();
for (char c : s.toCharArray()) {
map.put(c,map.getOrDefault(c,0)+1);
}
for (char c : t.toCharArray()) {
Integer orDefault = map.getOrDefault(c, 0);
map.put(c,--orDefault);
}
for (Integer value : map.values()) {
if(value!=0){
return false;
}
}
return true;
}
3、题目2:349-两个数组的交集
给定两个数组
nums1
和nums2
,返回它们的交集
- 输出结果中的每个元素一定是唯一的。我们可以不考虑输出结果的顺序 。
示例 1 :
输入: nums1 = [1,2,2,1], nums2 = [2,2]
输出: [2]
示例 2 :
输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出: [9,4]
解释: [4,9] 也是可通过的
思路:
1、既然是求交集,利用set 即可判断。
2、本题可以考虑什么时候用set,什么时候用map|数组。
代码:
public int[] intersection(int[] nums1, int[] nums2) {
HashSet<Integer> set = new HashSet<>();
HashSet<Integer> result = new HashSet<>();
for (int i : nums1) {
set.add(i);
}
for (int i : nums2) {
if(set.contains(i)){
result.add(i);
}
}
int[] array = result.stream().mapToInt(x -> x).toArray();
return array;
}
4、题目3:202-快乐数
编写一个算法来判断一个数
n
是不是快乐数。「快乐数」 定义为:
- 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
- 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
- 如果这个过程 结果为 1,那么这个数就是快乐数。
- 如果 n 是 快乐数 就返回 true ;不是,则返回 false 。
示例 1 : 输入: n = 19 输出: true 解释: 1(2) + 9(2) = 82 8(2) + 2(2) = 68 6(2) + 8(2) = 100 1(2) + 0(2) + 0(2) = 1 示例 2 : 输入: n = 2 输出: false
思路:
-
题目中说到会无限循环,也就是说求和过程中,sum 会重复出现,这个非常重要。
-
关于某个元素是否出现,可以使用 哈希法。
-
而判断是否重复出现可以使用 set
-
一个比较难的是求和,对各个位置的数进行取值,不熟悉
代码:
public boolean isHappy(int n){
HashSet<Integer> set = new HashSet<>();
while (n!=1 && !set.contains(n)){
set.add(n);
n = getNextNumber(n);
}
return n==1;
}
private int getNextNumber(int n) {
int res =0;
while (n>0){
int temp=n%10;
res +=temp*temp;
n=n/10;
}
return res;
}
5、题目4: 1-两数之和
给定一个整数数组
nums
和一个整数目标值target
,请你在该数组中找出 和为目标值target
的那 两个 整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。
你可以按任意顺序返回答案。
示例 1 : 输入: nums = [2,7,11,15], target = 9 输出: [0,1] 解释: 因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。 示例 2 : 输入: nums = [3,2,4], target = 6 输出: [1,2] 示例 3 : 输入: nums = [3,3], target = 6 输出: [0,1]
思路:
- 遍历,如果 map(index) - targe 存在,则代表找到值
- Map value 存储索引下标
public int[] twoSum(int[] nums, int target) {
HashMap<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
int val = target - nums[i];
if(map.containsKey(val)){
return new int[]{map.get(val),i};
}else{
map.put(nums[i],i);
}
}
return null;
}