在 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:完成每个集合元素的所有循环和遍历后,我们将映射对象的键以检查映射的任何键的长度是否等于数组的长度,这肯定会指示公共元素行为
步骤 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
时间和空间复杂度
由于我们使用 Map 和 Set 优化了算法,javascript 的强大概念将算法的时间复杂度从 O(n^2) 降低到 O(n),但由于 map 和 set 用于额外的内存分配,因此我们也牺牲了空间复杂度到线性时间,即 O(n)。
结论
这就是我们如何在编码环境中逻辑高效地思考上述问题陈述,将代码从嵌套循环转换为 Map 和 Set 功能,这使我们能够在线性时间和空间复杂度内使用它来遍历和执行操作。