使多个对象阵列相交



因此,首先,我不希望我的问题有一个具体的解决方案,而是希望更有经验的开发人员能给我一些启发,让我走上正轨。由于我在算法和数据结构方面还没有足够的经验,我认为这对我自己来说是一个挑战。

我有n个数组,其中n>=2.它们都包含对象,最后,我想要一个数组,它只包含所有这些数组之间的公共元素。

array1 = [{ id: 1 }, { id: 2 }, { id: 6 }, { id: 10 }]
array2 = [{ id: 2 }, { id: 4 }, { id: 10 }]
array3 = [{ id: 2 }, { id: 3 }, { id: 10 }]
arrayOfArrays = [array1, array2, array3]
intersect = [{ id: 2 }, { id: 10 }]

如何解决这个问题?我读过使用Divide And Conquer或Hash表的解决方案,甚至使用了lodash库,但我想实现我自己的解决方案一次,不依赖任何外部的东西,同时练习算法。

为了提高效率,我会从定位最短的数组开始。这应该是和你一起工作的人。您可以在arrayOfArrays上运行reduce来迭代并返回最短长度的索引。

const shortestIndex = arrayOfArrays.reduce((accumulator, currentArray, currentIndex) => currentArray.length < arrayOfArrays[index] ? currentIndex : accumulator, 0);

取最短的数组并再次调用reduce函数,这将遍历数组并允许您累积最终值。第二个参数是起始值,它是一个新数组。

shortestArray.reduce((accumulator, currentObject) => /*TODO*/, [])

对于代码,我们基本上需要遍历剩余的数组,并确保它存在于所有数组中。您可以使用every函数,因为它会快速失败,这意味着它不存在的第一个数组将触发它返回false。

every中,您可以调用some来检查是否至少有一个匹配项。

isMatch = remainingArrays.every(array => array.some(object => object.id === currentObject.id))

如果匹配,将其添加到累加器中,这将是您的最终结果。否则,只需返回蓄能器。

return isMatch ? [...accumulator, currentObject] : accumulator;

把所有这些放在一起应该会给你一个不错的解决方案。我相信还有更多的优化可以做,但这就是我的起点。

减少

每个

一些

一般的解决方案是迭代一个输入,并检查每个值是否存在于所有其他输入中。(时间复杂度:O(l * n * l),其中n是阵列的数量,l是阵列的平均长度(

根据其他两个答案的想法,我们可以通过稍微改进这种暴力方法

  • 通过最小输入进行迭代
  • 使用Set来高效查找id而不是迭代

所以它变成(O(l * n + min_l * n)=O(n * l)(

const arrayOfIdSets = arrayOfArrays.map(arr =>
new Set(arr.map(val => val.id))
);
const smallestArray = arrayOfArrays.reduce((smallest, arr) =>
smallest.length < arr.length ? smallest : arr
);
const intersection = smallestArray.filter(val =>
arrayOfIdSets.every(set => set.has(val.id))
);

处理这类问题的一个好方法,无论是在面试中还是在日常生活中,都是思考你能想出的最明显的方法,无论效率有多低,并思考如何改进它;暴力";方法

因此,对于这个问题,一个明显但效率低下的方法可能是遍历array1中的每一项,检查它是否同时在array2和array3中,如果是,则记下(在另一个数组中(。然后对array2和数组3中的每项重复一遍,确保只记下以前没有记下的项。

我们可以看到,这将是低效的,因为我们将多次在数组中查找单个项,这对于数组来说相当慢。但它会起作用的!

现在我们可以着手改进我们的解决方案了。需要注意的一点是,找到3个数组的交集与找到第三个数组与第一个和第二个数组的交点相同。因此,我们可以为2个数组的交集这一更简单的问题寻找解决方案,为3个数组构建一个交集。

这就是了解数据结构的方便之处。你希望能够提出这样的问题,";这个结构包含特定的元素吗"尽可能快。想想什么结构适合这种查找(称为搜索(。更有经验的工程师已经记住了这一点,但你可以参考https://www.bigocheatsheet.com/看看这组人擅长这个。

我将在此不给出完整的解决方案,但一旦您看到集合在插入和搜索方面都很快,请考虑如何使用它来解决您的问题。

最新更新