要求:生成集合所有可能组合的算法,不重复,或者递归调用函数返回结果。
在 JavaScript中的排列中提供的大多数(如果不是全部)答案?从循环或其他函数中递归调用函数以返回结果。
循环内递归函数调用示例
function p(a, b, res) {
var b = b || [], res = res || [], len = a.length;
if (!len)
res.push(b)
else
for (var i = 0; i < len
// recursive call to `p` here
; p(a.slice(0, i).concat(a.slice(i + 1, len)), b.concat(a[i]), res)
, i++
);
return res
}
p(["a", "b", "c"]);
当前的问题试图在线性过程中创建给定的排列,依赖于先前的排列。
例如,给定一个数组
var arr = ["a", "b", "c"];
确定可能排列的总数
for (var len = 1, i = k = arr.length; len < i ; k *= len++);
k
应该返回6
,或可能的排列总数arr
["a", "b", "c"]
为一组确定单个排列的总数后,可以使用Array.prototype.slice()
,Array.prototype.concat()
和填充包含所有六个排列的结果数组Array.prototype.reverse()
var res = new Array(new Array(k));
res[0] = arr;
res[1] = res[0].slice(0,1).concat(res[0].slice(-2).reverse());
res[2] = res[1].slice(-1).concat(res[1].slice(0,2));
res[3] = res[2].slice(0,1).concat(res[2].slice(-2).reverse());
res[4] = res[3].slice(-2).concat(res[3].slice(0,1));
res[5] = res[4].slice(0,1).concat(res[4].slice(-2).reverse());
试图再现基于模式结果在图表中显示的基础上发表的一项实用算法中的C有序排列辞书++算法在计算排列和面试问题。
例如,如果输入集是 ,则似乎存在可以扩展的模式
["a", "b", "c", "d", "e"]
其中预计有 120 个排列。
尝试仅依赖先前的排列来填充数组的示例
// returns duplicate entries at `j`
var arr = ["a", "b", "c", "d", "e"], j = [];
var i = k = arr.length;
arr.forEach(function(a, b, array) {
if (b > 1) {
k *= b;
if (b === i -1) {
for (var q = 0;j.length < k;q++) {
if (q === 0) {
j[q] = array;
} else {
j[q] = !(q % i)
? array.slice(q % i).reverse().concat(array.slice(0, q % i))
: array.slice(q % i).concat(array.slice(0, q % i));
}
}
}
}
})
但是现在还没有能够在对参数进行必要的调整.slice()
,.concat()
,.reverse()
在上面的js
步骤从一个排列到下一个; 而只使用其中的前一个数组条目res
来确定当前排列,而不使用递归。
注意到调用的偶数、奇数平衡,并尝试使用模数%
运算符和输入数组.length
来调用.reverse()
或不调用["a", "b", "c", "d", "e"]
数组,但没有产生没有重复条目的结果。
预期的结果是,上述模式可以减少到在整个过程中连续调用的两行,直到所有排列完成,res
填充;一呼一呼.reverse()
,不呼一呼.reverse()
;例如,res[0]
填充后
// odd , how to adjust `.slice()` , `.concat()` parameters
// for array of unknown `n` `.length` ?
res[i] = res[i - 1].slice(0,1).concat(res[i - 1].slice(-2).reverse());
// even
res[i] = res[1 - 1].slice(-1).concat(res[i - 1].slice(0,2));
问:调整上面的图案有什么必要,特别是参数或指标,传递.slice()
,.concat()
产生一组给定的所有可能的排列,而无需使用递归调用当前处理功能?
编辑、更新
已经找到了一个过程,可以使用上述模式.length
使用单个for
循环返回按字典顺序排列的排列,输入最多为4 。不为具有.length
of 的数组返回预期结果5
。
该模式基于“计算排列和求职面试问题” [ 0 ] 中的第二张图表。
不希望使用.splice()
或.sort()
返回结果,尽管在尝试遵守每列的最后一个“旋转”要求时在这里使用。变量r
应该引用index
下一个排列的第一个元素的 ,它确实这样做了。
使用的.splice()
,.sort()
如果它们的使用,随后在图表的图案可以被包括; 虽然在js
下面,他们实际上没有。
不完全确定js
下面的问题只是下面的陈述if (i % (total / len) === reset)
,尽管那部分需要最多的时间投入;但仍然没有返回预期的结果。
具体来说,现在参考图表,在旋转时,例如2
到 index 0
,1
到 index 2
。试图通过使用 来实现这一点r
,它是一个负索引,从右到左遍历以检索应该位于index
0
相邻“列”的下一个项目。
在下一列,2
将被放置在index
2
,3
将被放置在index
0
。这部分,就目前为止已经能够掌握或调试的,是发生错误的区域。
再次返回 的预期结果[1,2,3,4]
,但不是 for[1,2,3,4,5]
var arr = [1, 2, 3, 4];
for (var l = 1, j = total = arr.length; l < j ; total *= l++);
for (var i = 1
, reset = 0
, idx = 0
, r = 0
, len = arr.length
, res = [arr]
; i < total; i++) {
// previous permutation
var prev = res[i - 1];
// if we are at permutation `6` here, or, completion of all
// permutations beginning with `1`;
// setting next "column", place `2` at `index` 0;
// following all permutations beginning with `2`, place `3` at
// `index` `0`; with same process for `3` to `4`
if (i % (total / len) === reset) {
r = --r % -(len);
var next = prev.slice(r);
if (r === -1) {
// first implementation used for setting item at index `-1`
// to `index` 0
// would prefer to use single process for all "rotations",
// instead of splitting into `if` , `else`, though not there, yet
res[i] = [next[0]].concat(prev.slice(0, 1), prev.slice(1, len - 1)
.reverse());
} else {
// workaround for "rotation" at from `index` `r` to `index` `0`
// the chart does not actually use the previous permutation here,
// but rather, the first permutation of that particular "column";
// here, using `r` `,i`, `len`, would be
// `res[i - (i - 1) % (total / len)]`
var curr = prev.slice();
// this may be useful, to retrieve `r`,
// `prev` without item at `r` `index`
curr.splice(prev.indexOf(next[0]), 1);
// this is not optiomal
curr.sort(function(a, b) {
return arr.indexOf(a) > arr.indexOf(b)
});
// place `next[0]` at `index` `0`
// place remainder of sorted array at `index` `1` - n
curr.splice(0, 0, next[0])
res[i] = curr
}
idx = reset;
} else {
if (i % 2) {
// odd
res[i] = prev.slice(0, len - 2).concat(prev.slice(-2)
.reverse())
} else {
// even
--idx
res[i] = prev.slice(0, len - (len - 1))
.concat(prev.slice(idx), prev.slice(1, len + (idx)))
}
}
}
// try with `arr` : `[1,2,3,4,5]` to return `res` that is not correct;
// how can above `js` be adjusted to return correct results for `[1,2,3,4,5]` ?
console.log(res, res.length)
资源:
(倒计时) QuickPerm Head Lexicography: (Formally Example_03 ~ Palindromes)
生成所有排列 [非递归]
(尝试移植到 fromC++
到javascript
jsfiddle http://jsfiddle.net/tvvvjf3p/)