LeetCode第一天

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上的一张图看的明明白白:

fig1

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中的一部分数据,并进行处理即可。