哈希表理论基础
建议:大家要了解哈希表的内部实现原理,哈希函数,哈希碰撞,以及常见哈希表的区别,数组,set 和map。
什么时候想到用哈希法,当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法。 这句话很重要,大家在做哈希表题目都要思考这句话。
文章讲解:代码随想录
尽快看完java基础部分
242.有效的字母异位词
建议: 这道题目,大家可以感受到 数组 用来做哈希表 给我们带来的遍历之处。
文章讲解/视频讲解: 代码随想录
题目链接:242. 有效的字母异位词
自己写的:最长的用例过不了,不知道为啥
public boolean isAnagram(String s, String t) { if(s.length() != t.length()){ return false; } HashMap<String,Integer> map1 = new HashMap<>(); HashMap<String,Integer> map2 = new HashMap<>(); for(int i = 0 ; i<s.length();i++){ map1.put(s.substring(i,i+1), map1.getOrDefault(s.substring(i,i+1), 0) + 1); } for(int i = 0 ; i<t.length();i++){ map2.put(t.substring(i,i+1), map2.getOrDefault(t.substring(i,i+1), 0) + 1); } for(int i = 0 ; i<s.length();i++){ if(map1.get(s.substring(i,i+1)) != map2.get(s.substring(i,i+1))){ return false; } } return true; }
标准的代码:
public boolean isAnagram(String s, String t) { int[] record = new int[26]; for (char c : s.toCharArray()) { record[c - 'a'] += 1; } for (char c : t.toCharArray()) { record[c - 'a'] -= 1; } for (int i : record) { if (i != 0) { return false; } } return true; } 时间复杂度为O(n),空间上因为定义是的一个常量大小的辅助数组,所以空间复杂度为O(1)。
在字符数量确定的情况下可以用数组代替哈希表计数;
字符串转换成字符数组:
for (char c : s.toCharArray())
349. 两个数组的交集
建议:本题就开始考虑 什么时候用set 什么时候用数组,本题其实是使用set的好题,但是后来力扣改了题目描述和 测试用例,添加了 0 <= nums1[i], nums2[i] <= 1000 条件,所以使用数组也可以了,不过建议大家忽略这个条件。 尝试去使用set。
文章讲解/视频讲解:代码随想录
题目链接:
public int[] intersection(int[] nums1, int[] nums2) { HashMap<Integer,Integer> map1 = new HashMap<>(); HashMap<Integer,Integer> map2 = new HashMap<>(); ArrayList<Integer> list = new ArrayList<>(); for(int i : nums1){ map1.put(i, map1.getOrDefault(i, 0) + 1); } for(int i : nums2){ map2.put(i, map2.getOrDefault(i, 0) + 1); } for (int key : map1.keySet()){ if(map2.containsKey(key) ){ list.add(key); } } int[] array = list.stream().mapToInt(Integer::intValue).toArray(); return array; }
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; } 时间复杂度: O(mn) 空间复杂度: O(n)
202. 快乐数
建议:这道题目也是set的应用,其实和上一题差不多,就是 套在快乐数一个壳子
文章讲解:代码随想录
题目链接:202. 快乐数
public boolean isHappy(int n) { Set<Integer> record = new HashSet<>(); while (n != 1 && !record.contains(n)) { record.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; } 时间复杂度: O(logn) 空间复杂度: O(logn) #
记住位数操作
1. 两数之和
建议:本题虽然是 力扣第一题,但是还是挺难的,也是 代码随想录中 数组,set之后,使用map解决哈希问题的第一题。
建议大家先看视频讲解,然后尝试自己写代码,在看文章讲解,加深印象。
文章讲解/视频讲解:代码随想录
题目链接: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; }