Map哈希映射
哈希映射是用于存储 (key, value) 键值对的一种实现。
使用哈希映射的第一个场景是,我们需要更多的信息,而不仅仅是键。然后通过哈希映射建立密钥与信息之间的映射关系。
让我们来看一个例子:
给定一个整数数组,返回两个数字的索引,使它们相加得到特定目标。
在这个例子中,如果我们只想在有解决方案时返回 true,我们可以使用哈希集合来存储迭代数组时的所有值,并检查 target - current_value 是否在哈希集合中。
但是,我们被要求返回更多信息,这意味着我们不仅关心值,还关心索引。我们不仅需要存储数字作为键,还需要存储索引作为值。因此,我们应该使用哈希映射而不是哈希集合。
模板
/** Template for using hash map to find duplicates.* Replace ReturnType with the actual type of your return value.*/ReturnType aggregateByKey_hashmap(List<Type>& keys) {// Replace Type and InfoType with actual type of your key and valueMap<Type, InfoType> hashmap = new HashMap<>();for (Type key : keys) {if (hashmap.containsKey(key)) {if (hashmap.get(key) satisfies the requirement) {return needed_information;}}// Value can be any information you needed (e.g. index)hashmap.put(key, value);}return needed_information;}
两个数组的交集 II
题目描述:
(力扣链接🔗)

题目分析:
使用map来进行查重,此时选择map因为需要记录次数。也可以使用双指针法。
代码:
解法一:
/*** hash表(使用map) 时间复杂度:O(m+n) 空间复杂度:O(min(m,n))* @param nums1* @param nums2* @return*/public int[] intersect(int[] nums1, int[] nums2) {Map<Object, Integer> map = new HashMap<>();List<Integer> list = new ArrayList<>();// 将数字保存在map中,value存储次数for (int i = 0; i < nums2.length; i++) {map.put(nums2[i], map.getOrDefault(nums2[i], 0) + 1);}for (int i = 0; i < nums1.length; i++) {// map中存在且不为0if (map.containsKey(nums1[i]) && map.get(nums1[i]) != 0) {map.put(nums1[i], map.getOrDefault(nums1[i], 0) - 1);list.add(nums1[i]);}}// 转化为int数组int[] ints = new int[list.size()];int index = 0;for(Integer value : list) {ints[index++] = value;}return ints;}
解法二:
思路为2个数组分别使用2个指针进行遍历,在判断是否相等,不相等则移动指针。
/*** 排序 + 双指针** @param nums1* @param nums2* @return*/public int[] intersect(int[] nums1, int[] nums2) {// 将其进行排序,分别使用2个指针进行遍历Arrays.sort(nums1);Arrays.sort(nums2);int index = 0, index1 = 0, index2 = 0;int[] ints = new int[Math.min(nums1.length, nums2.length)]; // 用来保存交集// 2个指针一直向后判断,直到其中一个指针遍历完毕while (index1 < nums1.length && index2 < nums2.length) {// 谁小就向后移动if (nums1[index1] < nums2[index2]) {index1++;} else if (nums1[index1] > nums2[index2]) {index2++;} else { // 相等赋值进去即可ints[index] = nums1[index1];index++;index1++;index2++;}}// 将后面为0的截取掉return Arrays.copyOfRange(ints, 0, index);}
字母异位词
题目描述
力扣链接🔗

题目分析:
可以知道每个字符串字母都一样,但是顺序不同,可以先将字符串进行排序,在放到map中查找是否存在重复。此时map中的value不需要存储次数或者索引,所以我们可以使用value来存储复合条件的字符串集合。
代码:
class Solution {/*** map解法* @param strs* @return*/public List<List<String>> groupAnagrams(String[] strs) {HashMap<Object, List<String>> map = new HashMap<>();List<List<String>> list = new ArrayList<>();for (int i = 0; i < strs.length; i++) {String str = sort(strs[i]);if (map.containsKey(str)) {map.get(str).add(strs[i]);} else {List<String> stringList = new ArrayList<>();stringList.add(strs[i]);map.put(str, stringList);}}// 遍历将map中的value全部取出来for (Map.Entry<Object, List<String>> entry : map.entrySet()) {list.add(entry.getValue());}return list;}// 将其进行排序public String sort(String str) {char[] record = str.toCharArray();Arrays.sort(record);return String.valueOf(record);}}
两数之和
题目描述:
力扣链接🔗

题目分析:
- 数组的大小是受限制的,而且如果元素很少,而哈希值太大会造成内存空间的浪费。
 - set是一个集合,里面放的元素只能是一个key,而两数之和这道题目,不仅要判断y是否存在而且还要记录y的下标位置,因为要返回x 和 y的下标。所以set 也不能用。
 
使用map可以存储索引值。
代码:
class Solution {public int[] twoSum(int[] nums, int target) {Map<Integer, Integer> map = new HashMap<>();for (int i = 0; i < nums.length; i++) {// 相减后,判断后边是否存在temp即可int temp = target - nums[i];if (map.containsKey(temp)) {return new int[]{map.get(temp), i};}// 将索引作为valuemap.put(nums[i], i);}return new int[]{};}}
四数相加II
题目描述:
力扣链接🔗

题目分析:
- 首先定义 一个unordered_map,key放a和b两数之和,value 放a和b两数之和出现的次数。
 - 遍历大A和大B数组,统计两个数组元素之和,和出现的次数,放到map中。
 - 定义int变量count,用来统计 a+b+c+d = 0 出现的次数。
 - 在遍历大C和大D数组,找到如果 0-(c+d) 在map中出现过的话,就用count把map中key对应的value也就是出现次数统计出来。
 - 最后返回统计值 count 就可以了
 
巧妙的通过先计算2个数组中所有总和,并使用map来记录次数,在判断相加是否为0时,将0减去相加的数,即可转化为查重。
代码:
class Solution {public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {Map<Integer, Integer> map = new HashMap<>();int total = 0;for (int num1 : nums1) {for (int num2 : nums2) {// 将2数之和放入map,value保存出现的次数int temp = num1 + num2;map.put(temp, map.getOrDefault(temp, 0) + 1);}}for (int num3 : nums3) {for (int num4 : nums4) {// 在man中找相加等于0的数int temp = 0 - (num3 + num4);if (map.containsKey(temp)) {total += map.get(temp);}}}return total;}}
