拥有集合{a,b,c}我希望以递归方式查找所有子集。 我已经使用位掩码解决了这个问题,但我想了解一个人在此YouTube视频中说明的方式here
关于这个问题,还有其他的stackoverflow线程,但我没有发现任何解决她在视频中说明的方式,她说,
“获取a和b的子集,克隆它们然后将c添加到所有克隆”
我无法想象可以实现此目的的“简单”递归方法。一旦耗尽,递归方法是否具有A,B和A,B的克隆(此时重复)的所有子集,然后传播回来将C仅添加到克隆中?
换句话说,我开始在集合上使用for循环,我调用我的递归函数,然后我做一个n-1的for循环并在for循环中调用我的递归方法,我看不出我怎么能得到C要添加到使用递归构建的数组中已存在的子集克隆。
function SubsetBuilder(set) {
this.set = set;
}
SubsetBuilder.prototype.getSubsetsRecursive = function () {
//Set = {a,b,c}
//take the subsets of a and b, clone them and then add c to all the clones
//subsets of {a,b}=
//{}
//{a}
//{b}
//{a,b}
var n = this.set.length;
var result = [];
var recurseForSubsets = function (prefix, index) {
for (var i = index; i < n -1; i ++) {
result.push(prefix + this.set[i]);
recurseForSubsets(prefix + this.set[i], i + 1);
}
}
for (var j = 0; j < n; j++) {
recurseForSubsets("", j);
}
return result;
}
SubsetBuilder.prototype.printSubsets = function () {
var self = this;
if (!self.set)
return;
var n = this.set.length;
for (var i = 0; i < (1 << n) ; i++) {
var subset = [];
for (var j = 0; j < n; j++) {
if (((i >> j) & 1) === 1) { // bit j is on
subset.push(this.set[j]);
}
}
console.log(subset);
}
}
var set = ['a', 'b', 'c'];
var obj = new SubsetBuilder(set);
//obj.printSubsets();
console.log(obj.getSubsetsRecursive());
答案 0 :(得分:1)
我试了一下然后想出了
function getSubsets(inp) {
if (inp.length == 1) {
// return the single item set plus the empty set
return [inp, []];
} else {
var e = inp.pop();
var s = getSubsets(inp);
// duplicate the elements of s into s1 without creating references.
// this might not be the best technique
var s1 = s.concat(JSON.parse(JSON.stringify(s)));
// add e to the second group of duplicates
for (var i=s.length; i < s1.length; i++) {
s1[i].push(e);
}
return s1;
}
}
var set = ['a', 'b', 'c'];
var list = getSubsets(set);
console.log(list);
// result
// [["a"], [], ["a", "b"], ["b"], ["a", "c"], ["c"], ["a", "b", "c"], ["b", "c"]]
视频中的女士说,{a,b,c}
的所有子集都可以通过获取{a,b}
的所有子集并将c
附加到每个子集来形成。不完全准确({a,b,c}
的有效子集不必包含c
),而是算法的起始位置。我将规则更改为{a,b,c}
的所有子集,可以通过获取{a,b}
的子集的两个副本并将c
附加到第二个副本的每个元素来形成。
我想我可以摆脱或简化if
,因为基本上第二个代码块与第一个代码块相同,所以它并不理想。
对我而言,算法在O(2^n)
中运行是有意义的,因为结果以相同的方式变化(输入数组中的3个元素=输出数组中的2 ^ 3个元素) - 您可能不得不原谅我的但是使用JSON来假设复杂性。我会找到一种更好的方法来深度克隆数组,即便如此,这可能会增加更多的复杂性。