前言
复习了哈希表的内部实现原理,哈希函数,哈希碰撞,以及常见哈希表的区别,数组,set 和map。
当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法。
242.有效的字母异位词
题目链接:https://leetcode.cn/problems/valid-anagram/
暴力解法:2次排序,直接比较
class Solution {
public boolean isAnagram(String s, String t) {
char[] sChars = s.toCharArray();
char[] tChars = t.toCharArray();
Arrays.sort(sChars);
Arrays.sort(tChars);
return Arrays.equals(sChars, tChars);
}
}
哈希思想:存储每个字符的出现次数
public boolean isAnagram(String s, String t) {
Map<Character, Integer> map = new HashMap<>();
for(char c : s.toCharArray()) {
map.put(c, map.getOrDefault(c, 0) + 1);
}
for(char c : t.toCharArray()) {
Integer count = map.get(c);
if(count == null) {
return false;
} else if(count > 1) {
map.put(c, count - 1);
}else {
map.remove(c);
}
}
return map.isEmpty();
}
字典解法
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是字母异位词
}
}
349. 两个数组的交集
题目链接:https://leetcode.cn/problems/intersection-of-two-arrays/
哈希法
题目特意说明:输出结果中的每个元素一定是唯一的,也就是说输出的结果的去重的,
同时可以不考虑输出结果的顺序,这道题用暴力的解法时间复杂度是O(n^2)。
使用数组来做哈希的题目,是因为题目都限制了数值的大小。
而这道题目没有限制数值的大小,就无法使用数组来做哈希表了。
而且如果哈希值比较少、特别分散、跨度非常大,使用数组就造成空间的极大浪费。
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);
}
}
//方法1:将结果集合转为数组
//return resSet.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;
}
}
202. 快乐数
题目链接:https://leetcode.cn/problems/happy-number/description/
题目中说了会 无限循环,那么也就是说求和的过程中,sum会重复出现!
当遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法了。
所以这道题目使用哈希法,来判断这个sum是否重复出现,如果重复了就是return false, 否则一直找到sum为1为止。
class Solution {
public boolean isHappy(int n) {
Set<Integer> record = new HashSet<>();
while(n != 1 && !record.contains(n)) {
record.add(n);
n = getNextNum(n);
}
return n == 1;
}
private int getNextNum(int num) {
int sum = 0;
while(num > 0) {
int temp = num % 10;
sum += temp * temp;
num /= 10;
}
return sum;
}
}
1. 两数之和
题目链接:https://leetcode.cn/problems/two-sum/
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案
简单思路双重for循环遍历
class Solution {
public int[] twoSum(int[] nums, int target) {
for(int i = 0; i < nums.length; i++) {
for(int j = i + 1; j < nums.length; j++) {
if(nums[j] == target - nums[i]) {
return new int[]{i,j};
}
}
}
return new int[]{-1, -1};
}
}
优化,一个for循环,利用HashMap存储已经遍历过的数,key为值,value为索引
class Solution {
public int[] twoSum(int[] nums, int target) {
HashMap<Integer, Integer> map = new HashMap<>();
for(int i = 0; i < nums.length; i++) {
int temp = target - nums[i]; // 遍历当前元素,并在map中寻找是否有匹配的key
if(map.containsKey(temp)) {
return new int[]{i, map.get(temp)};
}
map.put(nums[i], i);
}
return new int[]{-1, -1};
}
}
今日总结
重新复习了哈希表的几种使用情况,以及何时进行使用。