LeetCode学习刷题-两个数组求交集350

146 阅读3分钟

「这是我参与11月更文挑战的第5天,活动详情查看:2021最后一次更文挑战

背景

比较巧的是在刷到LeetCode299题的时候,没过几天就刷到这个题目,里面的思路有联系,虽然这是一个简单题,但我觉得这个是一个比较有意义的题目,因此写一篇文章进行记录。

题目

给定两个数组,编写一个函数来计算它们的交集。
示例 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) 链接:leetcode-cn.com/problems/in…

思路

两种方案:哈希表和双指针
官方解析(可惜没有JavaScript的): leetcode-cn.com/problems/in…

代码以及代码分析

哈希表:

执行用时:104 ms, 在所有 JavaScript 提交中击败了5.32%的用户
内存消耗:40.1 MB, 在所有 JavaScript 提交中击败了14.43%的用户
参数是两个数组,首先定义一个哈希表,let m = new Map(),定义两个数组arr1是长度小的数组,arr2是长度大的数组,这个地方先进行判断,长度小的拷贝到arr1,长度大的拷贝到arr2。还需要定义一个res空数组。
接下来,把nums1用哈希表映射,这个循环先把哈希表元素对应的元素获取到,然后校验哈希表中是否有这个键值对,如果有就把k自增,然后就进行修改,如果没有这个键就新建,值默认为1.
随后遍历num2,找到一个哈希表对应的数少一个,在短数组中找到长数组的元素。咱们来看代码。temp暂存在arr1中找到arr2的下标结果。如果找到而且arr1的值还有(即大于0),则res数组添加这个,然后获取到k的值进行自减。最后res是我们要的结果。

双指针

执行用时: 76 ms, 在所有 JavaScript 提交中击败了62 .14 % 的用户
内存消耗: 40 MB, 在所有 JavaScript 提交中击败了17 .92 % 的用户
先定义两个数组存储参数排序后的结果,这里的sort用的是sort((a, b) => a - b),原因在之前文章中有提到。再定义res结果空数组,初始化左右指针为0.
用while循环,条件是left < arr1.length 并且 right < arr2.length,如果arr1和arr2相等了就把这个相等的值加到res数组里面,两个指针都移动。如果arr1[left] 大于 arr2[right]就right++,反之就left++,循环结束后的res就是我们需要的结果数组。

//方案1
var intersect = function (nums1, nums2) {
    let m = new Map();
    let arr1 = [];
    let arr2 = [];    
    if (nums1.length > nums2.length) {
        arr1 = [...nums2];
        arr2 = [...nums1];
    } else {
        arr1 = [...nums1];
        arr2 = [...nums2];
    }
    let res = [];
    // 1
    for (let i = 0; i < arr1.length; i++) {
        let k = m.get(arr1[i]);
        if (m.has(arr1[i])) {
            k++;
            m.set(arr1[i], k)
        } else {
            m.set(arr1[i], 1)
        }
    }
    // 2
    for (let i = 0; i < arr2.length; i++) {
        let temp = arr1.indexOf(arr2[i]);
        if (temp !== -1 && m.get(arr1[temp]) > 0) {
            res.push(arr1[temp]);
            let k = m.get(arr1[temp]);
            k--;
            m.set(arr1[temp], k);
        }
    }
    console.log(res);
};
intersect([1, 2, 2, 1], [2, 2])

//方案2
var intersect = function (nums1, nums2) {
    let arr1 = [...nums1].sort((a, b) => a - b);
    let arr2 = [...nums2].sort((a, b) => a - b);
    let left = 0;
    let right = 0;
    let res = []
    while (left < arr1.length && right < arr2.length) {
        if (arr1[left] === arr2[right]) {
            res.push(arr1[left])
            left++
            right++
        } else if (arr1[left] > arr2[right]) {
            right++
        } else left++
    }
    console.log(res);
};
intersect([43, 85, 49, 2, 83, 2, 39, 99, 15, 70, 39, 27, 71, 3, 88, 5, 19, 5, 68, 34, 7, 41, 84, 2, 13, 85, 12,
    54, 7, 9, 13, 19, 92
], [10, 8, 53, 63, 58, 83, 26, 10, 58, 3, 61, 56, 55, 38, 81, 29, 69, 55, 86, 23, 91, 44, 9, 98, 41, 48,
    41, 16, 42, 72, 6, 4, 2, 81, 42, 84, 4, 13
])
// [2,83,3,41,84,13,9]

说明

本文是作者用于学习时,在LeetCode刷题所见所想,引用了部分力扣资源,代码是根据大佬们思路进行写的,比起大佬们的代码,我的代码肯定有很大的优化空间了,如果是学习的建议访问力扣官网进行学习,本博客仅记录我的成长过程