柿子挑软的捏,所以我就先拿最软的来作为我小白的第一道,大佬求不要喷我。我只想买拿个一折优惠卷买两本小测。揪咪
看题:给定两个数组,编写一个函数来计算它们的交集。
两个数组的交集-349
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]
输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[9,4]
说明:
输出结果中的每个元素一定是唯一的。 我们可以不考虑输出结果的顺序。
前言:
在看到标题(取交集)中,我们脑海中会闪过那些数组的迭代方法,every()\some()\filter()\map()\forEach()\reduce()\find()\includes()\indexOf()等等等...
又看到我们现在有去重和不重两种。Es6最直观 Set去重。虽然无法去掉'{}'控对象,但我们现在也不考虑,或者遍历,利用indexOf、利用includes,甚至利用对象key的唯一性去去重,我们这里不在延伸,有兴趣,自行解决,嘿嘿。
脑海中闪过第一种解决方案:
var intersection = function(nums1, nums2) {
return [...new Set(nums1)].filter(item => nums2.includes(item));
};
心中暗暗窃喜一行代码就解决了,执行代码,提交,完事,下一道。
这里呢,我脑海中甚至都没有时间复杂度的概念,这时候跟暑假写作业一样,写完翻到最后找答案呀,立马答案对起来,我们官方题解立马摘抄出来给大家。
思路想法
计算两个数组的交集,直观的方法是遍历数组 nums1,对于其中的每个元素,遍历数组 nums2 判断该元素是否在数组 nums2 中,如果存在,则将该元素添加到返回值。假设数组 nums1 和 nums2 的长度分别是 mm 和 nn,则遍历数组 nums1 需要 O(m) 的时间,判断 nums1 中的每个元素是否在数组 nums2 中需要 O(n) 的时间,因此总时间复杂度是 O(mn)。
哈希表解法
如果使用哈希集合存储元素,则可以在 O(1) 的时间内判断一个元素是否在集合中,从而降低时间复杂度。
首先使用两个集合分别存储两个数组中的元素,然后遍历较小的集合,判断其中的每个元素是否在另一个集合中,如果元素也在另一个集合中,则将该元素添加到返回值。该方法的时间复杂度可以降低到 O(m+n)。
var intersection = function(nums1, nums2) {
const set1 = new Set(nums1);
const set2 = new Set(nums2);
return set_intersection(set1, set2)
};
function set_intersection(set1, set2){
if(set2.length > set1.length) {
return set_intersection(set2, set1);
}
const intersection = new Set();
for(let num of set1){
set2.has(num) && intersection.add(num);
}
return [...intersection];
}
这里利用哈希表我觉得更有助于我们理解整个流程,找到去重后最短的数组,声明一个新数组,遍历找到另外一个数组所共同拥有的数值,然后返回我们的新数组。
哈希表复杂度分析
-
时间复杂度:O(m+n),其中 m 和 n 分别是两个数组的长度。使用两个集合分别存储两个数组中的元素需要 O(m+n) 的时间,遍历较小的集合并判断元素是否在另一个集合中需要 O(min(m,n)) 的时间,因此总时间复杂度是 O(m+n)。
-
空间复杂度:O(m+n),其中 m 和 n 分别是两个数组的长度。空间复杂度主要取决于两个集合。
排序 + 双指针解法
我觉得排序与双指针用大白话来说就是,先把数组排序,大家头对头,脚对脚来进行对比,第一步对比,ok,你头大你牛皮,我找我老大(下一个,较小数字指针向右移一位),大家头一样大,好的存起来(同时将两个指针右移一位),最后大家再令出来,大家一起看~
代码copy出来~
var intersection = function(nums1, nums2) {
nums1.sort((x, y) => x - y);
nums2.sort((x, y) => x - y);
const length1 = nums1.length, length2 = nums2.length;
let index1 = 0, index2 = 0;
const intersection = [];
while (index1 < length1 && index2 < length2) {
const num1 = nums1[index1], num2 = nums2[index2];
if (num1 === num2) {
// 保证加入元素的唯一性
if (!intersection.length || num1 !== intersection[intersection.length - 1]) {
intersection.push(num1);
}
index1++;
index2++;
} else if (num1 < num2) {
index1++;
} else {
index2++;
}
}
return intersection;
};
排序+双指针复杂度分析
-
时间复杂度:O(mlogm+nlogn),其中 m 和 n 分别是两个数组的长度。对两个数组排序的时间复杂度分别是 O(mlogm) 和 O(nlogn),双指针寻找交集元素的时间复杂度是 O(m+n)O(m+n),因此总时间复杂度是 O(mlogm+nlogn)。
-
空间复杂度:O(logm+logn),其中 m 和 n 分别是两个数组的长度。空间复杂度主要取决于排序使用的额外空间。 ”本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情