一、题目核心
题干要求
给定两个整数数组 nums1 和 nums2,返回它们的交集。输出结果中每个元素出现的次数,需与元素在两个数组中出现次数的最小值一致,不考虑顺序。
二、两种核心解法
解法 1:1 个 Map 最优解(推荐!时间 + 空间双优)
核心思路
- 用 1 个 Map 统计「较短数组」的元素出现次数(省空间);
- 遍历较长数组,遇到 Map 中存在的元素就加入结果,同时将 Map 中该元素次数 - 1;
- 次数为 0 时删除元素,自动满足 "取最小次数" 要求。
代码实现
java
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class Solution {
public int[] intersect(int[] nums1, int[] nums2) {
// 统计较短数组,优化空间
if (nums1.length > nums2.length) return intersect(nums2, nums1);
HashMap<Integer, Integer> countMap = new HashMap<>();
for (int num : nums1) {
// getOrDefault解决key首次出现为null的问题
countMap.put(num, countMap.getOrDefault(num, 0) + 1);
}
List<Integer> resList = new ArrayList<>();
for (int num : nums2) {
if (countMap.containsKey(num) && countMap.get(num) > 0) {
resList.add(num);
countMap.put(num, countMap.get(num) - 1);
}
}
// List转数组返回
return resList.stream().mapToInt(Integer::intValue).toArray();
}
}
复杂度
- 时间:O (m+n)(线性遍历,最快)
- 空间:O (min (m,n))(仅存较短数组元素)
解法 2:排序 + 双指针(省空间,适配空间限制场景)
核心思路
- 两数组排序,利用排序后重复元素相邻的特性;
- 双指针遍历,元素相等则加入结果(天然取最小次数),不等则小指针后移。
代码实现:
java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Solution {
public int[] intersect(int[] nums1, int[] nums2) {
Arrays.sort(nums1);
Arrays.sort(nums2);
int i = 0, j = 0;
List<Integer> resList = new ArrayList<>();
while (i < nums1.length && j < nums2.length) {
if (nums1[i] == nums2[j]) {
resList.add(nums1[i]);
i++;
j++;
} else if (nums1[i] < nums2[j]) {
i++;
} else {
j++;
}
}
int[] res = new int[resList.size()];
for (int k = 0; k < resList.size(); k++) res[k] = resList.get(k);
return res;
}
}
复杂度
- 时间:O (m logm + n logn)(排序占主要耗时)
- 空间:O (1)(忽略排序系统栈空间,纯省空间)
总结
这道题的核心是「统计次数 + 取最小次数」,两种解法覆盖不同场景