嵌套 for 循环 - 如何忽略某些组合?

2024-01-09

我正在进行某种暴力攻击来解决问题。从理论上讲,这是一个可行的解决方案,实际上也是如此,但需要相当长的时间。

我有 7 个相互嵌套的 for 循环,但我只需要“for 变量”的组合,其中不重复。所以例如允许使用 1,2,3,4,5,6,7,但应忽略 1,1,3,4,5,6,7。我目前正在使用一个函数来检查数组中的重复项:

http://www.groggyjava.tv/freebies/duplicates.html http://www.groggyjava.tv/freebies/duplicates.html

不过,我认为如果我可以立即忽略这些组合而不是一遍又一遍地使用该函数,我会更好every单一组合。现在我正在评估 14^7 = 105.413.504 个组合,但只需要其中 14 nPr 7 = 17.297.280 个组合。

我当前的代码是(其中 hgd 是重复测试函数,如果没有重复则返回 true):

for(var a=0;a<14;a++) {
    for(var b=0;b<14;b++) {if(hgd([a,b])) {
        for(var c=0;c<14;c++) {if(hgd([a,b,c])) {
            for(var d=0;d<14;d++) {if(hgd([a,b,c,d])) {
                for(var e=0;e<14;e++) {if(hgd([a,b,c,d,e])) {
                    for(var f=0;f<14;f++) {if(hgd([a,b,c,d,e,f])) {
                        for(var g=0;g<14;g++) {if(hgd([a,b,c,d,e,f,g])) {
                            check([a,b,c,d,e,f,g]);
                        }}
                    }}
                }}
            }}
        }}
    }}
}

我怎样才能使它更快,是否有另一种解决方案而不是 for 循环?

Thanks.


你在这里所做的是迭代所有排列14 个离散值的列表。

一般来说,要访问离散事物列表的所有排列,您需要访问列表中的每个元素。对于每个元素,形成一个包含所有元素的新列表other原始列表的元素。得到所有的排列that列表,将元素添加到每个元素之前,您就获得了可以以该特定元素开头的原始列表的所有排列。当你完成所有元素后,你就完成了。

当然,查找包含一个元素的列表的所有排列是一项简单的任务。

因此我们得到的是这样的:

function forEachPermutation(list, operation) {
  function pluckElement(list, index) {
    var e = list[index];
    var l = [];
    for (var i = 0; i < list.length; ++i)
      if (i !== index) l.push(list[i]);
    return { element: e, remainder: l };
  }

  function permute(partial, remainder) {
    if (remainder.length === 0)
      operation(partial);
    else {
      for (var i = 0; i < remainder.length; ++i) {
        var plucked = pluckElement(remainder, i);
        partial.push(plucked.element);
        permute(partial, plucked.remainder);
        partial.length--;
      }
    }
  }

  permute([], list);
}

它的作用是递归地执行我上面描述的操作。 “pluckElement”函数从列表中返回一个元素,并且rest该列表中的。然后,“permute”函数要么执行对原始列表的完整排列传入的操作(当它注意到剩余列表为空时),要么使用它传递的列表的每个元素递归地调用自身。

要使用该功能,您只需执行以下操作:

forEachPermutation([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], check);

edit— 如果您只想从原始列表中提取一定数量的值,则必须修改上述内容;稍等片刻。

好的 - 如果您想传入(例如)14 个元素的列表,但为 14 个(例如)7 个元素的每个不同列表调用“操作”函数,您可以按如下方式修改该函数。外部“forEachPermutation”函数将采用额外的“len”参数,以告诉它所需的字符串长度。然后,“permute”函数将检查“partial.length”是否是目标长度,而不是检查空余数。

function forEachPermutation(list, len, operation) {
  function pluckElement(list, index) {
    var e = list[index];
    var l = [];
    for (var i = 0; i < list.length; ++i)
      if (i !== index) l.push(list[i]);
    return { element: e, remainder: l };
  }

  function permute(partial, remainder) {
    if (partial.length === len)
      operation(partial);
    else {
      for (var i = 0; i < remainder.length; ++i) {
        var plucked = pluckElement(remainder, i);
        partial.push(plucked.element);
        permute(partial, plucked.remainder);
        partial.length--;
      }
    }
  }

  permute([], list);
}

你会这样称呼它

forEachPermutation([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], 7, check);

另一个编辑— 如果出于某种原因你想要save“操作”函数处理每个排列后的排列,那么我们必须考虑正在使用的部分数组被覆盖的事实。对“操作”的调用可以更改:

if (partial.length === len)
  operation(partial.slice(0));

这会生成“部分”数组的副本,以便每次调用“操作”时都会获得自己的数组来使用。当然,这会让这个过程变慢。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

嵌套 for 循环 - 如何忽略某些组合? 的相关文章

随机推荐