我正在做某种蛮力攻击来解决问题.理论上它是一个有效的解决方案,它确实是,但它需要相当长的时间.
我有7个嵌套for循环,但我只需要'for variables'的组合,其中没有重复.因此,例如允许1,2,3,4,5,6,7,但应忽略1,1,3,4,5,6,7.我目前正在使用一个函数来检查数组中的重复项:
http://www.groggyjava.tv/freebies/duplicates.html
但是我想我会离开,如果我能马上忽视这些组合,而不是反复使用该功能更好的每一个组合.现在我正在评估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]);
}}
}}
}}
}}
}}
}}
}
Run Code Online (Sandbox Code Playgroud)
我怎么能让这个更快,是否有另一个解决方案而不是循环?
谢谢.
你在这里做的是迭代14个谨慎值列表的所有排列.
通常,要访问一系列谨慎事物的所有排列,您可以访问列表中的每个元素.对于每个元素,形成一个包含原始列表的所有其他元素的新列表.获取该列表的所有排列,将元素添加到每个列表中,并且您已获得可以从该特定元素开始的原始列表的所有排列.当你完成所有元素后,你就完成了.
当然,查找包含一个元素的列表的所有排列是一项简单的任务.
因此,我们得到的是这样的:
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);
}
Run Code Online (Sandbox Code Playgroud)
这样做是递归地执行我上面描述的操作."pluckElement"函数返回列表中的元素以及该列表的其余部分.然后,"置换"函数或者执行在原始列表的完整排列中传递的操作(当它注意到剩余列表为空时),或者以传递的列表的每个元素递归地调用自身.
要使用该功能,您只需执行以下操作:
forEachPermutation([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], check);
Run Code Online (Sandbox Code Playgroud)
编辑 - 如果您只想从原始列表中提取一定数量的值,则必须修改上述值; 稍等片刻.
OK - 如果你想传入一个(例如)14个元素的列表,但是为14个中的每个不同的列表(例如)调用了"operation"函数,你可以修改函数如下.外部"forEachPermutation"函数将采用额外的"len"参数,以告诉它所需字符串的长度.然后,"置换"函数将检查"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);
}
Run Code Online (Sandbox Code Playgroud)
你打电话给它
forEachPermutation([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], 7, check);
Run Code Online (Sandbox Code Playgroud)
另一个编辑 - 如果出于某种原因你想在"操作"函数处理每一个之后保存排列,那么我们必须考虑到正在使用的部分数组被覆盖的事实.可以更改对"操作"的调用:
if (partial.length === len)
operation(partial.slice(0));
Run Code Online (Sandbox Code Playgroud)
这使得"部分"数组的副本成为可能,因此每次"操作"调用都会获得它自己的数组.当然,它会让这个过程变慢.
| 归档时间: |
|
| 查看次数: |
366 次 |
| 最近记录: |