sisterAn / JavaScript-Algorithms

基础理论+JS框架应用+实践,从0到1构建整个前端算法体系

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

阿里算法题:编写一个函数计算多个数组的交集

sisterAn opened this issue · comments

要求:
输出结果中的每个元素一定是唯一的

commented
var intersection = function (nums1, nums2) {
  let arr1 = Array.from(new Set(nums1));
  let arr2 = Array.from(new Set(nums2));
  let arr3 = new Array();
  for (let [v, k] of arr1.entries()) {
    if (arr2.includes(k)) {
      arr3.push(k)
    }
  }
  return arr3;
};
// 忽略我的命名......
const intersection = (arrs) => {

  /** @returns { Set } intersection 两个集合的交集*/
  const intersectTwoSets = (set1, set2) => {
    const result = new Set(set1)
    for (let item of result) {
      if (!set2.has(item)) {
        result.delete(item)
      }
    }
    return result
  }

  /** @description 所有数组的交集 */
  const resultSet = (
    arrs
      .map(arr => new Set(arr))
      // O(N * M)
      .reduce(intersectTwoSets) 
  )

  return Array.from(resultSet)
}

万能的reduce

const getIntersection = (...arrs) => {
    return Array.from(new Set(arrs.reduce((total, arr) => {
        return arr.filter(item => total.includes(item));
    })));
}
function intersect(arrs) {
      let obj = {},
        result = {};
      for (let i = 0; i < arrs[0].length; i++) {
        obj[i] = 1;
      }
      for (let i = 1; i < arrs.length; i++) {
        result = {};
        arrs[i].forEach(element => {
          obj[element] ? (result[element] = 1) : "";
        });
        obj = result;
      }

      return Object.keys(obj);
    }

一行代码搞定

let intersection = (list , ...args) => list.filter( item => args.every( list => list.includes( item )))
console.log( intersection( [ 2,1 ], [ 2,3 ] ) ) // [ 2 ]
console.log( intersection( [ 2,1 ], [ 4,3 ] ) ) // [ ]
/**
 * 编写一个函数计算多个数组的交集,要求结果中的每个元素都是唯一的
 */

function multArrMerge() {
  let arrs = Array.prototype.slice.call(arguments).map(item => Array.from(new Set(item)));
  let shortArr = arrs[0];
  let mergeArr = [];

  // O(n)
  // 找到最短数组
  arrs.forEach((item, index) => {
    if (shortArr.length > item.length) {
      shortArr = item;
    }
  });

  // O(n^2)
  // 收集最短数组中每个元素的交集
  mergeArr = shortArr.map(item => {
    const temp = [];
    arrs.forEach(item1 => {
      if (item1.indexOf(item) > -1) {
        temp.push(item);
      }
    });
    return temp;
  });

  // O(n)
  // 过滤每个数组的交集
  mergeArr = mergeArr.map(item => {
    if (item.length === arrs.length) {
      return item[0];
    }
  }).filter(item => item)

  return mergeArr;
}

function multArrMerge(...arrs) {
  arrs = arrs.map(item => Array.from(new Set(item)));
  let targetArr = arrs[0];
  for (let i = 1, len = arrs.length; i < len; i++) {
    targetArr = arrs[i].filter(item => targetArr.includes(item));
  }
  return targetArr;
}
function intersection(arr,...args){
  // 记录每次对比两个数组的交集
  let set = new Set(arr);
  for(let e of args){ // 取出不定个参数数组
    let rep = []; // 记录当前数组和之前交集的交集
    for(let ele of e){
      if(set.has(ele)){
        rep.push(ele);
      }
    }
    set = new Set(rep); // 将交集用于和下组数组的对比
  }
  return [...set];
}

在原先两个数组求交集的基础上使用reduce

function intersect(nums1,nums2){
   return [...new Set(nums1.filter((item)=>nums2.includes(item)))]
}
function intersectAll(...arrs){
    return resultArr = arrs.reduce(function(prev,cur){
	return intersect(prev,cur);
    })
}

合并之后就是

function getIntersect(...arrs) {
    return arrs.reduce(function(prev,cur){
	return [...new Set(cur.filter((item)=>prev.includes(item)))]
    })
}
const mixed = (...arrs) => {
  return [...new Set(arrs.reduce((sum,arr) => {
    return arr.filter(i => sum.includes(i));
  }))]
}
commented
function intersection(...arr) {
    let result = [];
    arr.forEach(arr => {
        if( arr instanceof Array ){
            // 如果是第一个数组,则直接将该数组去重然后 push 到目标数组中
            if( !result.length ) {
                result.push(...new Set(arr));
                return ;
            }
            // 如果是第二个及以后的数组,则先去重然后用目标数组过滤
            const tempSet = new Set(arr);
            result = result.filter(item=>tempSet.has(item));
        }
    });
    return result;
}
commented
var intersection = function (...arrs) {
  let res= arrs[0]
  for (let i = 1; i < arrs.length; i++) {
    res = res.filter(item=> arrs[i].includes(item))    
  }
  return [...new Set(res)]
}
commented
function intersection(){
  return Array.prototype.slice.call(arguments).reduce((arr, item) => {
        return item.filter(key => arr.includes(key));
  })
}

使用 reducer 函数

const intersection = function(...args) {
    if (args.length === 0) {
    return []
  }
  if (args.length === 1) {
    return args[0]
  }
  return [...new Set(args.reduce((result, arg) => {
    return result.filter(item => arg.includes(item))
  }))]
};
const intersection = function(...rest) {
        console.log('rest', rest);
        const arr = rest.reduce((prev, next) => {
            console.log('prev', prev);
            console.log('next', next);
            if (prev.length === 0) {
                prev = prev.concat(next);
            } else {
                // prev = [...new Set(prev.filter(item => next.includes(item)))]; 每次计算 prev 值都会进行一次去重
                prev = prev.filter(item => next.includes(item));
            }
            return prev;
        }, []);
        return [...new Set(arr)]; // 不如计算完之后统一去一次重
    };

var intersection = function() {
console.log(arguments);
const setList = [...new Set(arguments[0])];
const list = [];
setList.forEach(num => {
let tag = true;
for (let i = 1; i < arguments.length; i++) {
if (!arguments[i].includes(num)) {
tag = false;
break;
}
}
if (tag) {
list.push(num);
}
});
return list;
}

  console.log(intersection([1,2,4, 5], [1,5,6,7], [1,3,5,6,8]));

需要注意的地方:
1、交集中的每一项,在每个数组中都要存在,所以用到了every
2、需要考虑去重,有可能一个数据在每个数组中多次出现

    const intersection = function(list, ...args) {
            return [
                ...new Set(list.filter(item => args.every(temp => temp.includes(item))))
            ]
        }
    intersection([2,1,2], [3], [2,5,6,6,3]) // []
    intersection([2,1,2], [1,2,3], [2,5,6,6,3]) // [2]

function merge(){
let args = Array.prototype.slice.call(arguments);
let col = 0, new_obj = {}, len = args.length, new_arr = [];
while(col<args.length){
let row = args[col].length - 1,cache_arr = [];
while(row>=0){
if(new_obj[args[col][row]]){
new_obj[args[col][row]] = ++new_obj[args[col][row]];
}else{
new_obj[args[col][row]] = 1;
}
// console.log(new_obj, args[col][row])
if(new_obj[args[col][row]]>=len){
cache_arr.push(args[col][row])
}
row--;
new_arr = cache_arr;
}
col++
}
// console.log(new_obj)
return new_arr;
}

commented

1

function twoIntersection(p, n) {
  const map = {}
  const res = []
  p.forEach((key) => {
    map[key] = 1
  })

  n.forEach((key) => {
    if (map[key]) {
      map[key]++
      if (map[key] === 2) {
        res.push(key)
      }
    }
  })
  return res
}

const intersection = (...arrs) => arrs.reduce(twoIntersection)

2

const intersection = (first, ...rest) => [
  ...new Set(first.filter((item) => rest.every((arr) => arr.includes(item)))),
]
const intersection2 = (...arrays) => {
  if (arrays.length === 0) {
    return []
  }

  if (arrays.length === 1) {
    return arrays[ 0 ]
  }

  return [ ...new Set(arrays.reduce((result, array) => {
    return result.filter((it) => array.includes(it))
  }))]
}
    function intersection (arrays) {
            let result = []
            let resMap = {}
            let tempArrays = arrays.flat(2)
            for (let num of tempArrays) {
                if (resMap[num]) {
                    result.push(num)
                } else {
                    resMap[num] = num
                }
            }
            return [...new Set(result)]
        }

`
function intersection(arr1, arr2) {
const a1 = new Set([...arr1]);
return Array.from(new Set([...arr2.filter(item => a1.has(item))]));
}

`

commented
function intersection(arrs) {
  function intersectionTwo(nums1, nums2) {
    return Array.from(new Set(nums1.filter(v => nums2.includes(v))))
  }
  return arrs.reduce(intersectionTwo)
}

// 多个数组取交集(三个及以上)
// 原数组
const serveralArr = [
[1,2,4,5,23,3,2,2,4,3,5,5],
[3,2,3,2,2,4,3,1,4,5,6],
[3,2,4,3,2,4,1,2,5],
[3,2,4,5,5,4,3,1,2,2],
[3,2,23,3,4,1,3,4,5,5,4,3,1,2,2],
[3,2,4,1,2,5,5,4,3,1,2,2],
[3,2,4,25,5,4,3,1,2,2],
]
// ES5 方法实现数学意义上的交集结果
const intersectNoRepeatFirst = serveralArr => {
let minArr = serveralArr[0]
serveralArr.forEach(item => {
if(item.length < minArr.length){
minArr = item
}
})
const result = []
minArr.forEach(item => {
serveralArr.forEach(j => {
if(j.includes(item) && !result.includes(item)){
result.push(item)
}
})
})
return result
}
// ES6 方法实现数学意义上的交集结果
const intersectNoRepeatTwice = arrs => {
return arrs.reduce(function(prev,cur){
// return [...new Set(cur.filter((item)=>prev.includes(item)))]
return Array.from(new Set(cur.filter((item)=>prev.includes(item))))
})
}
// 输出数学意义上的交集结果
console.log(intersectNoRepeatFirst(serveralArr), intersectNoRepeatTwice(serveralArr)) // => (5) [3, 2, 4, 1, 5]; (5) [3, 2, 4, 5, 1]
// ES5 方法实现有重复元素的交集结果
const intersectRepeat = arr => {
const result = []
const tempArr = []
arr.forEach(item => {
const obj = {}
item.forEach(j => {
if(obj.hasOwnProperty(j)){
obj[j] += 1
}else{
obj[j] = 1
}
})
tempArr.push(obj)
})
let arrr = tempArr[0]
tempArr.forEach(item => {
if(item.length < arrr.length){
arrr = item
}
})
const newOjb = {}
Object.keys(arrr).forEach(item => {
newOjb[item] = Math.min.apply(Math, tempArr.map(function(o) {return o[item]}))
})
Object.keys(newOjb).forEach(item => {
if(newOjb[item]){
for(let i = 0; i < newOjb[item]; i++){
result.push(Number(item))
}
}
})
return result
}
// 输出有重复元素的交集结果
console.log(intersectRepeat(serveralArr)) // => (9) [1, 2, 2, 2, 3, 3, 4, 4, 5]

万能的reduce

const getIntersection = (...arrs) => {
    return Array.from(new Set(arrs.reduce((total, arr) => {
        return arr.filter(item => total.includes(item));
    })));
}

It's helpful for me.

function getArr(...argument) {
      if (argument.length === 0) {
        return []
      }
      return calc(argument)
    }

    function calc(arr) {
      const len = arr.length
      if (len === 1) {
        return arr[0]
      }
      const mid = Math.floor(len / 2)
      const right = arr.slice(0, mid)
      const left = arr.slice(mid, len)
      return calcTwo(calc(right), calc(left))
    }

    function calcTwo(arr1, arr2) {
      const len1 = arr1.length
      const len2 = arr2.length
      if (len2 > len1) {
        [arr1, arr2] = [arr2, arr1]
      }
      return Array.from(new Set(arr1.filter(v => arr2.includes(v))))
    }
commented
commented
commented
commented