乐趣区

大厂面试算法之两个数组求交集

给定两个数组,用一个函数计算出二者交加。

let num1 = [1,2,2,1];
let num2 = [2,2]; 
// 求出 [2,2]
let num1 = [4,9,5];
let num2 = [9,4,9,8,4];
// 求出 [4,9]

办法一

存哈希表

因为同一个数字在两个数组中都可能呈现屡次,因而须要用哈希表记录每个数字呈现的次数。对于同一个数字,其在交集中呈现的次数等于该数字在两个数组中呈现次数的最小值。

首先遍历第一个数组,并在哈希表中记录第一个数组中的每个数字以及对应呈现的次数,而后遍历第二个数组,对于第二个数组中的每个数字,如果在哈希表中存在这个数字,则将该数字增加到答案,同时缩小哈希表中该数字呈现的次数。

为了升高空间复杂度,首先遍历较短的数组并在哈希表中记录每个数字以及对应呈现的次数,而后遍历较长的数组失去交加。

const intersect = (num1, num2) => {const map = {};
  const res = [];
  for (const n1 of num1) { // 存下 num1 数字的呈现次数
    if (map[n1]) {map[n1]++;  
    } else {map[n1] = 1; 
    }
  }
  for (const n2 of num2) { // 遍历 num2 看看有没有数字在 num1 呈现过
    const val = map[n2];
    if (val > 0) {            // 呈现过
      res.push(n2);         // 推入 res 数组
      map[n2]--;            // 匹配掉一个,就少了一个
    }
  }
  return res;
};

运行后果:

let num1 = [1,2,2,1];
let num2 = [2,2]; 
console.log(intersect(num1,num2));        //[2,2]

办法二

双指针形式

如果两个数组是有序的,则能够便捷地计算两个数组的交加。

首先对两个数组进行排序,而后应用两个指针遍历两个数组。

初始时,两个指针别离指向两个数组的头部。每次比拟两个指针指向的两个数组中的数字,如果两个数字不相等,则将指向较小数字的指针右移一位,如果两个数字相等,将该数字增加到答案,并将两个指针都右移一位。当至多有一个指针超出数组范畴时,遍历完结。

const intersect = (num1, num2) => {num1.sort((a, b) => a - b);
  num2.sort((a, b) => a - b); // 先排序,使得反复的元素相邻呈现
  const res = [];
  let p1 = 0;                  // 两个指针
  let p2 = 0;
  while (p1 < num1.length && p2 < num2.length) { // 用 && 因为有一个越界了就不能找交加
    if (num1[p1] > num2[p2]) {        // p1 指向的数大,挪动 p2,期待遇到一样大的
      p2++;
    } else if (num1[p1] < num2[p2]) { // 相似
      p1++;
    } else {                   // 遇到雷同的,推入 res 数组,两个指针同时挪动考查下一个
      res.push(num1[p1]);
      p1++;
      p2++;
    }
  }
  return res;
};

运行后果:

let num1 = [4,9,5];
let num2 = [9,4,9,8,4];
console.log(intersect(num1,num2));        //[4,9]

办法三

最简略的双重循环

const intersect = (num1, num2) => {const res = [];
    for(let i=0;i<num1.length;i++){for(let j=0;j<num2.length;j++){if(num1[i] == num2[j]){res.push(num1[i]);
                num1.splice(i,1); 
                i--;        // 删除元素后索引需前移
                num2.splice(j,1); 
                break;
            }
        }
    }
    return res;
};

不解释

退出移动版