LeetCode第350题
给定两个数组,编写一个函数来计算它们的交集。
示例 1:
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2,2]
示例 2:
输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[4,9]
说明:
输出结果中每个元素出现的次数,应与元素在两个数组中出现次数的最小值一致。
我们可以不考虑输出结果的顺序。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/intersection-of-two-arrays-ii
方法一:
用哈希表映射,先把较短的那个数组遍历,存入哈希表中,键是数组中元素的值,值是数组中元素出现的次数
再遍历另外一个数组,从哈希表中找这个数组中的值,看是否存在,存在就将其存入新造的数组中,再将哈希表中该键对应的值减一,如果值减到了0,就将这个键移除去,否则将这个键对应的值减一,在存入哈希表中。
这个方法LeetCode上的一张图看的明明白白:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| private static int[] intersect1(int[] nums1, int[] nums2) { if (nums1.length > nums2.length) { return intersect1(nums2, nums1); } Map<Integer, Integer> map = new HashMap<>(); for (int num : nums1) { int count = map.getOrDefault(num, 0) + 1; map.put(num, count); } int[] arr = new int[nums2.length]; int index = 0; for (int num : nums2) { int count = map.getOrDefault(num, 0); if (count > 0) { arr[index++] = num; if (count != 1) { map.put(num, --count); } else { map.remove(num); } } } return Arrays.copyOfRange(arr, 0, index); }
|
方法二:
先对两个数组进行排序,然后设置两个指针来遍历这两个数组。将比较结果较小的那个数组的指针后移,如果两数相等,则将两个数组的指针都向后移,并将这个数存入新造好的数组。遍历直到有一个指针到了数组的结尾,结束遍历。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| private static int[] intersect2(int[] nums1, int[] nums2) { Arrays.sort(nums1); Arrays.sort(nums2); int len1 = nums1.length, len2 = nums2.length; int index1 = 0, index2 = 0, index = 0; int[] arr = new int[Math.min(len1, len2)]; while (index1 < len1 && index2 < len2) { if (nums1[index1] < nums2[index2]) { index1++; } else if (nums1[index1] > nums2[index2]) { index2++; } else { arr[index++] = nums1[index1]; index1++; index2++; } }
return Arrays.copyOfRange(arr, 0, index); }
|
结语
如果 nums2的元素存储在磁盘上,磁盘内存是有限的,并且你不能一次加载所有的元素到内存中。那么就无法高效地对 nums2进行排序,因此推荐使用方法一而不是方法二。在方法一中,nums2 只关系到查询操作,因此每次读取nums2中的一部分数据,并进行处理即可。