给定两个数组,编写一个函数来计算它们的交集
示例 1:
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]
示例 2:
输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[9,4]
说明:
- 输出结果中的每个元素一定是唯一的。
- 我们可以不考虑输出结果的顺序。
这题比较简单,有很多种方法和思路!如果你觉得自己会了,就不需要往下看了!下面我们介绍下一些常用的思路和方法并加于分析!
遍历循环
直观的方法是遍历数组 nums1,对于其中的每个元素,遍历数组 nums2 判断该元素是否在数组 nums2 中,如果存在,则将该元素添加到返回值。假设数组 nums1 和 nums2 的长度分别是 m 和 n,则遍历数组 nums1 需要 O(m)的时间,判断 nums1 中的每个元素是否在数组 nums2 中需要 O(n)的时间,因此总时间复杂度是 O(mn)。这种方法大家最容易想到,也是最耗时的!
let intersection = (nums1,nums2) => {
let arr = [];
for (var i = 0; i < nums1.length; i++) {
for (var j = 0; j < nums2.length; j++) {
if (nums1[i] === nums2[j]) {
arr.push(nums1[i]);
};
};
};
return [...new Set(arr)];
}
遍历循环(变种)
可以在 O(1)的时间内判断一个元素是否在集合中,从而降低时间复杂度。先遍历较小的集合,判断其中的每个元素是否在另一个集合中,如果元素也在另一个集合中,则将该元素添加到返回值。该方法的时间复杂度可以由相乘降低到相加。
let intersection = (nums1, nums2) => {
let arr = [];
if (nums1.length > nums2.length) {
return intersection(nums2, nums1);
};
for (let item of nums1) {
if (nums2.includes(item)) arr.push(item);
};
return [...new Set(arr)];
};
set+filter
let intersection = (nums1, nums2) => {
return [...new Set(nums1)].filter((item) => {
return nums2.includes(item);
});
};
reduce+indexOf
let intersection = (nums1, nums2) => {
return nums1.reduce((prev, next) => !prev.includes(next) && nums2.includes(next) ? [...prev, next] : prev, []);
};
排序+双指针
首先对两个数组进行排序,然后使用两个指针遍历两个数组。初始时,两个指针分别指向两个数组的头部。每次比较两个指针指向的两个数组中的数字,如果两个数字不相等,则将指向较小数字的指针右移一位,如果两个数字相等,把此数字加入答案中(去同操作),同时将两个指针都右移一位。当至少有一个指针超出数组范围时,遍历结束。
let intersection = (nums1, nums2) => {
let i = 0,
j = 0;
arr = [];
nums1 = nums1.sort((a, b) => {
return a - b;
});
nums2 = nums2.sort((a, b) => {
return a - b;
});
while (i < nums1.length && j < nums2.length) {
if (nums1[i] == nums2[j]) {
arr.includes(nums1[i]) ? arr : arr.push(nums1[i]);
i++;
j++;
} else if (nums1[i] > nums2[j]) {
j++;
} else {
i++;
};
};
return arr;
};
排序+二分法查找
把第一个数组排序,然后遍历第二个数组的值,判断是否在第一个数组中,这里使用的是二分法查找(不懂的点击这里),看下代码
let intersection = (nums1, nums2) => {
nums2.sort((a, b) => a - b);
let arr = [];
let binarySearch = (number, arr) => {
let left = 0;
let right = arr.length - 1;
while (left <= right) {
let middle = parseInt((left + right) / 2);
if (number == arr[middle]) {
return true
} else if (number > arr[middle]) {
left = middle + 1;
} else if (number < arr[middle]) {
right = middle - 1;
};
};
return false;
};
for (var i = 0; i < nums1.length; i++) {
if (binarySearch(nums1[i], nums2)) {
arr.push(nums1[i]);
};
};
return [...new Set(arr)];
}