JavaScript 中查找任意数量数组的公共元素
问题陈述要求您为任意数量的数组找到解决方案,以便用户需要找到每个任意数组中存在的公共元素。这里将任意数组称为数组对象。不应将查找两个数组之间的公共元素与之混淆,这不是问题陈述所要求的。它定义并探索了各种可以帮助我们找到 JavaScript 中给定源数据中存在的互斥最小公因数的算法。
什么是 JavaScript 中的任意数量数组
任意数量是指不遵循任何特定模式的不确定的大量值,您只需随机为它们提供值。类似地,任意数量的数组是指给定随机元素的两个以上数组集,其中如此数量的不同数组被打包在一个称为数组对象的 对象中。问题陈述说要查找此类随机、不同且超过两个可数数组集中存在的交集元素。
不同的数组集可以打包在数组的数组或数组的对象中,因为问题陈述中没有提到此类条件。
此处的算法讨论了解决数组本身中存在的任意数量数组的问题陈述。
步骤 1:声明一个名为 findCommonElements 的函数,该函数以数组输入作为源。
步骤 2:声明并初始化结果数组为空数组。
步骤 3:使用外部 for 循环遍历所有任意数组的第一个数组,其中 i 索引将跟踪第一个数组及其元素从 arr.length-1 的反向方向开始,因为在存在大量数组或数组中有多个数组的情况下,每次迭代循环时计算 length 属性效率不高,这并不够简单。
步骤 4:嵌套的第二个循环将遍历剩余的数组集或大型数组中存在的剩余任意数组,并使用 j 索引。
步骤 5:indexOf 方法用于查找第一个数组中存在的元素的值到剩余的任意集中。
步骤 6:如果在剩余数组中找不到第一个数组的特定值,我们只需使用 break 语句跳到下一次迭代并尝试查找其他任意数组中存在的公共元素。
步骤 7:所有循环结束后,我们使用 j 索引来判断其值是否已到达第一个数组本身,这是比较的主要来源,只需将比较过程中从 arr[0][i] 获得的任何值推送到结果数组中,因为数组不能与自身进行比较。
主代码 - 使用循环
示例
function findCommonElements(arr) { let commonArray = []; for (let i = arr[0].length - 1; i >= 0; i--) { let isCommon = true; for (let j = arr.length - 1; j > 0; j--) { if (arr[j].indexOf(arr[0][i]) === -1) { isCommon = false; break; } } if (isCommon) { commonArray.push(arr[0][i]); } } return commonArray; } const arrayOfArrays = [ [1, 4, 6, 78, 8, 9, 124, 44], [44, 6, 9], [124, 44, 16, 9] ]; console.log(findCommonElements(arrayOfArrays));
输出
[ 44, 9 ]
时间和空间复杂度
在上述算法中,我们使用了嵌套循环,该循环一直持续到数组的长度,因此在最坏情况下导致 O(n^2) 的时间复杂度。空间复杂度为 O(1)
上述算法可以通过遵循 JavaScript 中的映射和集合进行优化
算法 - 使用 Map 和 Set
该算法在时间复杂度方面现在效率更高,但肯定牺牲了空间复杂度,
步骤 1:声明一个名为 commonElementFind 的函数,该函数以 mainArray 作为输入源。
步骤 2:声明并初始化一个带有空值的映射。
步骤 3:我们将遍历数组的每个子数组,以在 JavaScript 中创建并转换每个子数组为 Set,以去除重复项并使算法在查找任意数量数组中存在的公共元素方面更高效、更快捷
步骤 4:一旦每个子数组转换为每个唯一的集合,我们现在将通过计算它们在整个公共和单个映射中的出现次数来设置它们的映射值
步骤 5:如果集合的值已存在于映射中,则将其递增 1,否则将其初始化并赋值为 1
步骤 6:一旦所有循环和每个 Set 元素的遍历完成,我们将映射对象的键以检查映射的任何键的长度是否等于数组的长度,这肯定会表明公共元素的行为
步骤 7:一旦我们找到等于数组长度的键,这意味着该特定元素已出现在数组的所有子数组中,因此我们在 JavaScript 中找到任意数量数组中存在的公共元素或值。
主代码 - 使用 Map 和 Set
示例
function commonElementFind(mainArray) { const newMap = {}; for(let subArray of mainArray) { const newSet = new Set(subArray); newSet.forEach(val => { if(newMap[val]) { newMap[val] = newMap[val] + 1; } else { newMap[val] = 1; } }) } Object.keys(newMap).map((key)=> { if(newMap[key] === arr.length) { console.log(key); } }); } const arr = [ [15, 23, 36, 49, 104, 211], [9, 12, 23], [11, 17, 18, 23, 38], [13, 21, 23, 27, 40, 85] ]; commonElementFind(arr);
输出
23
时间和空间复杂度
由于我们使用 JavaScript 的强大概念 Map 和 Set 优化了算法,因此它将算法的时间复杂度从 O(n^2) 降至 O(n),但由于 Map 和 Set 用于额外的内存分配,我们也牺牲了空间复杂度以达到线性时间,即 O(n)。
结论
这就是我们如何在编码的上下文中以逻辑和有效的方式解决上述问题陈述的方式,将代码从嵌套循环更改为 Map 和 Set 功能,这使我们拥有巨大的能力来遍历和使用它执行操作,从而实现线性时间和空间复杂度。