数组 - 两个数组的交集 II

题目

https://leetcode-cn.com/explore/interview/card/top-interview-questions-easy/1/array/26/

个人解法

测试用例数(个) 执行用时(ms) 战胜
61 92 98.88%
var setCache = function (cache, num) {
    if (!cache[num]) {
        cache[num] = 1;
    } else {
        cache[num] = cache[num] + 1;
    }
}

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number[]}
 */
var intersect = function(nums1, nums2) {
    var cacheLong = {};
    var cacheShort = {};

    var numsLong = [];
    var numsShort = [];

    var result = [];

    if (nums1.length > nums2.length) {
        numsLong = nums1;
        numsShort = nums2;
    } else {
        numsLong = nums2;
        numsShort = nums1;
    }

    var i = 0;

    while(i < numsLong.length) {
        if (numsLong[i] !== undefined) {
            setCache(cacheLong, numsLong[i]); 
        }
        
        if (numsShort[i] !== undefined) {
            setCache(cacheShort, numsShort[i]); 
        }

        i++;
    }

    for (var k in cacheShort) {
        if (cacheLong[k] && cacheShort[k]) {
            var count = cacheLong[k] > cacheShort[k]
                ? cacheShort[k]
                : cacheLong[k];

            for (var i = 0 ; i < count ; i++) {
                result.push(k);
            }
        }
    }

    return result;
};

最快解法

测试用例数(个) 执行用时(ms) 战胜
61 72 100%
/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number[]}
 */
var intersect = function(nums1, nums2) {
  const map = {}
  if (nums1.length > nums2.length) [nums1, nums2] = [nums2, nums1]
  nums1.forEach(num => {
    if (!map[num]) map[num] = 1
    else map[num]++
  })
  return nums2.filter(num => {
    if (map[num] > 0) {
      map[num]--
      return true
    }
    return false
  })
};

分析

两种解法本质类似,都是通过 cache 缓存记录次数。

「个人解法」是分别计算出两个数组的 cache 结果,从而进行比较,得出交集。

而「最快解法」中,是只计算出最长数组的 cache 结果,同事将其用到较短数组的过滤逻辑当中,直接得出交集。

进阶问题

如果给定的数组已经排好序呢?你将如何优化你的算法?
var intersect = function (num1, num2) {
    const result = [];

    let n1i = 0;
    let n2i = 0;

    while (num1[n1i] !== undefined && num2[n2i] !== undefined) {
        let n1 = num1[n1i];
        let n2 = num2[n2i];

        if (n1 === n2) {
            result.push(n1);

            n1i++;
            n2i++;
        } else if (n1 > n2) {
            n2i++;
        } else {
            n1i++;
        }
    }

    return result;
}
如果 nums1 的大小比 nums2 小很多,哪种方法更优?
var intersect = function (num1, num2) {
    const cache1 = {};
    const resule = [];
    let matchIndex = 0;

    num1.forEach(v => {
        if (cache1[v]) {
            cache1[v] += 1;
        } else {
            cache1[v] = 1;
        }
    });

    for (let i = 0 ; i < num2.length ; i++) {
        let n2 = num2[i];

        if (matchIndex >= num1.length) {
            break;
        } else {
            if (cache1[n2]) {
                resule.push(n2);

                cache1[n2]--;
                matchIndex++;
            }
        }
    }

    return result;
}
果 nums2 的元素存储在磁盘上,磁盘内存是有限的,并且你不能一次加载所有的元素到内存中,你该怎么办?

采取分批加载策略,对于每批的算法,同上。

*****
Written by Zheng Yu on 13 May 2019