给定两个数组,编写一个函数来计算它们的交集。
说明:
- 输出结果中的每个元素一定是唯一的。
- 我们可以不考虑输出结果的顺序。
解法一
set
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
// set
Set<Integer> set = new HashSet<>();
// 对nums1数组进行排序
Arrays.sort(nums1);
// 遍历nums2的每个元素
for (int num2 : nums2) {
// 对比nums1中的元素
for (int num1 : nums1) {
// 相等保存到set中
if (num1 == num2) {
set.add(num1);
break;
}
// 如果num1已经大于num2,说明这个数不是交集,跳出循环
if (num1 > num2) {
break;
}
}
}
// 转成数组
int[] ret = new int[set.size()];
int i = 0;
for (int num : set) {
ret[i++] = num;
}
return ret;
}
}
虽然剪枝了但是用双for效率还是不行。
解法二
二分查找
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
// 二分查找
// 对nums1数组进行排序
Arrays.sort(nums1);
Set<Integer> set = new HashSet<>();
// 遍历nums2数组
for (int target : nums2) {
// 每个元素都到nums1数组中二分查找
int l = 0, r = nums1.length - 1;
while (l <= r) {
// 取中位下标
int mid = l + (r - l) / 2;
if (target < nums1[mid]) {
r = mid - 1;
} else if (target > nums1[mid]) {
l = mid + 1;
} else {
// 相等,保存到set中
set.add(target);
break;
}
}
}
// 转成数组
int[] ret = new int[set.size()];
int i = 0;
for (int num : set) {
ret[i++] = num;
}
return ret;
}
}
对解法一进行优化,用二分查找。
解法三
双set
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
// 双set
Set<Integer> set1 = new HashSet<>();
Set<Integer> set2 = new HashSet<>(); // 存放交集元素
// 先把nums1数组的所有元素放到set中
for (int num : nums1) {
set1.add(num);
}
// 遍历nums2数组,如果nums2的元素存在于set1中,放入set2中
for (int num : nums2) {
if (set1.contains(num)) {
set2.add(num);
}
}
// 转成数组
int[] ret = new int[set2.size()];
int i = 0;
for (int num : set2) {
ret[i++] = num;
}
return ret;
}
}
再优化,使用两个set,时间复杂度变为O(1)。
解法四
set + list
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
// set + list
// 第二个set,也可以换成list,只要有符合的元素放入list时,移除掉set中的元素即可
Set<Integer> set = new HashSet<>();
List<Integer> list = new ArrayList<>(); // 存放交集元素
// 先把nums1数组的所有元素放到set中
for (int num : nums1) {
set.add(num);
}
// 遍历nums2数组,如果nums2的元素存在于set中,放入list中,并移除掉set中的元素
for (int num : nums2) {
if (set.contains(num)) {
list.add(num);
set.remove(num);
}
}
// 转成数组
int[] ret = new int[list.size()];
int i = 0;
for (int num : list) {
ret[i++] = num;
}
return ret;
}
}
思路来着题解区数据结构和算法
大佬的题解。
解法五
双指针
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
// 双指针
// 对两个数组进行排序
Arrays.sort(nums1);
Arrays.sort(nums2);
Set<Integer> set = new HashSet<>();
int i1 = 0, i2 = 0;
while (i1 < nums1.length && i2 < nums2.length) {
// nums1元素大,i2指针往后移一位
if (nums1[i1] > nums2[i2]) {
i2++;
} else if (nums1[i1] < nums2[i2]) {
// nums1元素小,i1指针往后移一位
i1++;
} else {
// 相等,保存到set中
set.add(nums1[i1]);
i1++;
i2++;
}
}
// 转成数组
int[] ret = new int[set.size()];
int i = 0;
for (int num : set) {
ret[i++] = num;
}
return ret;
}
}
如果题目有给出取值范围,并且范围不大的话,可以用数组进行统计,然后比较,不过既然没给出,那么也用不了这种方法了。