Javascript 防止循环中的循环。如何降低复杂性

Javascript 防止循环中的循环。如何降低复杂性,javascript,arrays,performance,time-complexity,space-complexity,Javascript,Arrays,Performance,Time Complexity,Space Complexity,您有两个阵列。 阿拉是空的。 arrB充满了东西(它充满了什么并不重要,但假设它是巨大的) 当用户执行某项操作时,将从arrB中删除一项,并将该项放置在arrA中 当用户做不同的事情时,它会从arrA中提取项目并将其放入arrB中 有没有可能在循环中没有循环的情况下执行此操作 或者用计算机科学术语来说: 是否可以使用线性(ϴ(n))时间/空间复杂性来实现这一点? 现在我有一些至少是ϴ(n*k)的东西 (其中n是arrB的长度,k是传递给applyItems的项目数): var arrA=[],

您有两个阵列。
阿拉是空的。
arrB充满了东西(它充满了什么并不重要,但假设它是巨大的)

当用户执行某项操作时,将从arrB中删除一项,并将该项放置在arrA中

当用户做不同的事情时,它会从arrA中提取项目并将其放入arrB中

有没有可能在循环中没有循环的情况下执行此操作

或者用计算机科学术语来说:
是否可以使用线性(ϴ(n))时间/空间复杂性来实现这一点?
现在我有一些至少是ϴ(n*k)的东西

(其中n是arrB的长度,k是传递给applyItems的项目数):

var arrA=[],arrB=[1,2,3,4,5,6,7,8,9,0];
函数addToArray(arrayToAddTo,项){
if(arrayToAddTo.indexOf(项)=-1){
arrayToAddTo.push(项目);
}
}
函数removeFromArray(arrayToRemoveFrom,项){
var i=arrayToRemoveFrom.length;
var-temp=[];
而(我--){
if(arrayToRemoveFrom[i]!==项){
温度推送(阵列从[i]移除);
}   
}
返回温度;
}
函数应用项(arrayOfItems){
var i=阵列长度;
而(我--){
无功电流=阵列电流[i]
addToArray(阿拉,当前);
arrB=从阵列中移除(arrB,当前);
}
}
应用项([0,5,3]);
控制台日志(arrA);

控制台日志(arrB)是。您可以使用

因此,您可以只执行
arrB.splice(i,1),而不是
removeFromArray(arrB,current)
。这将从索引
i
中删除
1
元素

您不需要在每个元素上循环检查它是否与您想要的匹配,只需使用即可。所以你可以做一些像

 var i = arrA.indexOf(item)
根据我的评论:


您可以使用比手动循环快得多的本机工具。removeFromArray可以使用indexOf获取要删除的位置,然后使用splice将其删除。您还可以使用引用,而不是每次都重新创建数组

通过其他一些优化

var arrA = [], arrB = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];

function addToArray(item){
  if(arrA.indexOf(item) === -1){
    arrA.push(item);
  }
}

function removeFromArray(item){
  var index = arrB.indexOf(item);
  if (index > -1) {
    arrB.splice(index, 1);
  }
}

function applyItems(arrayOfItems){
  arrayOfItems.map(function(item) {
      addToArray(item);
      removeFromArray(item);
  });
}

applyItems([0, 5, 3]);
console.log(arrA);
console.log(arrB);
现在我有一些至少是ϴ(n*k)的东西

通过对
arrayOfItems
使用一种高效的查找结构,您可以使其成为
O(n+k)
,该结构不需要循环,但允许您在
O(1)
中确定一个项是否应交换到另一个数组中。这样,一次通过
arrB
就足够了。
或者,如果您对数组排序并使用二进制搜索进行查找,您将得到
O(log k*(n+k))
。然而,如果你的数组是有限的,而且非常小,那就不重要了


您还应该在
addToArray
中省略
indexOf
测试。似乎可以确定
arrA
arrB
中都没有项目(并且您的算法保持不变),因此在将项目推送到阵列之前,您不必检查重复项。

您可以使用比手动循环快得多的本机工具
removeFromArray
可以使用
indexOf
获取要删除的位置,然后使用
splice
将其删除。您还可以使用引用,而不是每次都重新创建数组。类似于这样的情况?-,修改了
removeFromArray
方法以避免循环并使用拼接方法。我看不出您当前的方法是如何
O(n²)
。它是
O(n*k)
,其中
n
arrB
中的项数,
k
arrayOfItems
中的项数。这个复杂度完全没有问题。不过,您可能希望在
addToArray
中省略
indexOf
。似乎可以确定
arrA
arrB
中都没有项目(并且您的算法保持不变),因此在将项目从一个项目交换到另一个项目之前,您不必检查重复项other@AndrewLuhring:是的,您可以使其
O(n+k)
通过对
arrayOfItems
使用高效的查找结构,该结构不需要循环,但允许您在
O(1)
中确定是否应交换项。这样,单次通过
arrB
就足够了。但是,如果数组是有限的(并且非常小),这几乎无关紧要。通过循环数组中的项,拼接不起作用吗?另外,indexOf不是也循环遍历数组中的项吗?是的,我相信两者都是O(n)。我把你的问题解释为,你如何不必循环就能做到。我的错。应该澄清一下。这更像是一个算法问题,而不是特定于JavaScript的问题。为什么您认为“本机工具”比手动循环快得多?此外,它们仍然具有相同的复杂性。与@Bergi相同的点-拼接不是通过循环数组中的项来工作吗?另外,indexOf是否也循环遍历数组中的项?仅仅因为它是一个内置函数并不意味着它的使用效率很高。我发现@Bergi提到的想法是因为我这一次从python翻译了一些代码。该函数使用了python的“sum”函数(我认为它通过循环数组将数组中的所有值相加)。据我所知,javascript中没有等价物,但即使有,在循环中使用它也不会有效率,因为您已经在循环中循环了。javascript是一种解释语言,这一事实从定义上讲比编译语言慢。因此,使用本机javascript函数总是更快,因为它们是在引擎中编译的。但是,嘿,让自己尝试一下,试着战胜它@AndrewLuhring:即使在python中,也可以尝试手动或使用
sum
对元素求和,您将看到很大的不同。这不是复杂性的问题,而是代码执行环境的问题。一个是由计算机解释的一系列字节码,另一个在执行前有一层解释器和编译器。